Update
This commit is contained in:
parent
5c43f56dc3
commit
1c2717e515
8 changed files with 48 additions and 29 deletions
16
algorithm.md
16
algorithm.md
|
@ -1,18 +1,18 @@
|
|||
# Algorithm
|
||||
|
||||
Algorithm (from the name of Persian mathematician Muhammad ibn Musa al-Khwarizmi) is an exact step-by-step description of how to solve some type of a problem. Algorithms are basically what [programming](programming.md) is all about: we tell [computers](computer.md), in very exact ways (with [programming languages](programming_language.md)), how to solve problems -- we write algorithms. But algorithms don't have to be just computer programs, they are simply instruction for solving problems.
|
||||
Algorithm (from the name of Persian mathematician Muhammad ibn Musa al-Khwarizmi) is an exact step-by-step description of how to solve some type of a problem. Algorithms are basically what [programming](programming.md) is all about: we tell [computers](computer.md), in very exact ways (with [programming languages](programming_language.md)), how to solve problems -- we write algorithms. But algorithms don't have to be just computer programs, they are simply exact instruction for solving problems.
|
||||
|
||||
Cooking recipes are commonly given as an example of a non-computer algorithm, though they rarely contain branching ("if then...") and loops ("while a condition holds do ..."), the key features of algorithms. The so called wall-follower is a simple algorithm to get out of any [maze](maze.md): you just pick either a left-hand or right-hand wall and then keep following it. You may write a crazy algorithm basically for any kind of problem, e.g. for how to clean a room or how to get a [girl](woman.md) to bed, but it has to be **precise** so that anyone can execute the algorithm just by blindly following the steps; if there is any ambiguity, it is not considered an algorithm; a vague, imprecise "hint" on how to find a solution (e.g. "to get to the airport head somewhere in this direction.") we rather call a [heuristic](heuristic.md). Heuristics are useful too and they may be utilized by an algorithm, e.g. to find a precise solution faster, but from programmer's point of view algorithms, the PRECISE ways of finding solutions, are the basic of everything.
|
||||
Cooking recipes are commonly given as an example of a non-computer algorithm, though they rarely contain branching ("if condition holds then do...") and loops ("while a condition holds do ..."), the key features of algorithms. The so called wall-follower is a simple algorithm to get out of any [maze](maze.md) which doesn't have any disconnected walls: you just pick either a left-hand or right-hand wall and then keep following it. You may write a crazy algorithm basically for any kind of problem, e.g. for how to clean a room or how to get a [girl](woman.md) to bed, but it has to be **precise** so that anyone can execute the algorithm just by blindly following the steps; if there is any ambiguity, it is not considered an algorithm; a vague, imprecise "hint" on how to find a solution (e.g. "the airport is somewhere in this general direction.") we rather call a [heuristic](heuristic.md). Heuristics are useful too and they may be utilized by an algorithm, e.g. to find a precise solution faster, but from programmer's point of view algorithms, the PRECISE ways of finding solutions, are the basics of everything.
|
||||
|
||||
Interesting fact: contrary to intuition there are problems that are mathematically proven to be unsolvable by any algorithm, see [undecidability](undecidability.md), but for most practically encountered problems we can write an algorithm (though for some problems even our best algorithms can be unusably [slow](time_complexity.md)).
|
||||
|
||||
Algorithms are mostly (possibly [not always](declarative.md), depending on exact definition of the term) written as a **series of steps** (or instructions); these steps may be specific actions (such as adding two numbers or drawing a pixel to the screen) or **conditional jumps** to other steps ("if condition X holds then jump to step N, otherwise continue"). At the lowest level ([machine code](machine_code.md), [assembly](assembly.md)) computers can do just that: execute instructions (expressed as [1s and 0s](binary.md)) and perform conditional jumps. These jumps can be used to create **[branches](branch.md)** (in programming known as *if-then-else*) and **[loops](loop.md)**. Branches and loops are together known as [control structures](control_structure.md) -- they don't express a direct action but control which steps in the algorithm will follow. All in all, **any algorithm can be written with only these three constructs**:
|
||||
Algorithms are mostly (possibly [not always](declarative.md), depending on exact definition of the term) written as a **series of steps** (or "instructions"); these steps may be specific actions (such as adding two numbers or drawing a pixel to the screen) or **conditional jumps** to other steps ("if condition X holds then jump to step N, otherwise continue"). At the lowest level ([machine code](machine_code.md), [assembly](assembly.md)) computers cannot do anything more complex than that: execute simple instructions (expressed as [1s and 0s](binary.md)) and perform conditional jumps -- in this computers are quite dumb (their strength comes from being able to execute many instruction with extreme speed). These jumps can be used to create **[branches](branch.md)** (in programming known as *if-then-else*) and **[loops](loop.md)**. Branches and loops are together known as [control structures](control_structure.md) -- they don't express a direct action but control which steps in the algorithm will follow. All in all, **any algorithm can be built just using these three basic constructs**:
|
||||
|
||||
- **sequence**: A series of steps, one after another. E.g. "write prompt, read number from input, store than number to memory".
|
||||
- **selection** (branches, *if-then-else*): Two branches (sequences of steps) preceded by a condition; the first branch is executed only if the condition holds, the second ("else") branch is executed only if the condition doesn't hold (e.g. "If user password is correct, log the user in, otherwise print out an error.").
|
||||
- **iteration** (loops, repetition): Sequence of steps that's repeated as long as certain condition holds (e.g. "As long as end of file is not reached, read and print out next character from the file.").
|
||||
- **sequence**: A series of steps, one after another. E.g. "write prompt, read number from input, multiply it by two, store it to memory".
|
||||
- **selection** (branches, *if-then-else*): Two branches (blocks of instructions) preceded by a condition; the first branch is executed only if the condition holds, the second ("else") branch is executed only if the condition doesn't hold (e.g. "If user password is correct, log the user in, otherwise print out an error."). The second branch is optional (it may remain empty).
|
||||
- **iteration** (loops, repetition): Sequence of steps that's repeated as long as certain condition holds (e.g. "As long as end of file is not reached, read and print out the next character from the file.").
|
||||
|
||||
Note: in a wider sense algorithms may be expressed in other ways than sequences of steps (non-[imperative](imperative.md) ways, see [declarative languages](declarative.md)), even mathematical equations are often called algorithms because they *imply* the steps towards solving a problem. But we'll stick to the common meaning of algorithm given above.
|
||||
Note: in a wider sense algorithms may be expressed in other (mathematically equivalent) ways than sequences of steps (non-[imperative](imperative.md) ways, see [declarative languages](declarative.md)), even mathematical equations are often called algorithms because they *imply* the steps towards solving a problem. But we'll stick to the common narrow meaning of algorithm given above.
|
||||
|
||||
Additional constructs can be introduced to make programming more comfortable, e.g. [subroutines/functions](function.md) (kind of small subprograms that the main program uses for solving the problem), [macros](macro.md) (shorthand commands that represent multiple commands) or [switch](switch.md) statements (selection but with more than two branches). Loops are also commonly divided into several types such as: counted loops, loops with condition and the beginning, loops with condition at the end and infinite loops (`for`, `while`, `do while` and `while (1)` in [C](c.md), respectively) -- in theory there can only be one generic type of loop but for convenience programming languages normally offer different "templates" for commonly used loops. Similarly to mathematical equations, algorithms make use of [variables](variable.md), i.e. values which can change and which have a specific name (such as *x* or *myVariable*).
|
||||
|
||||
|
@ -20,7 +20,7 @@ Practical programming is based on expressing algorithms via [text](text.md), but
|
|||
|
||||
## Example
|
||||
|
||||
Let's write a simple algorithm that counts the number of divisors of given number *x* and checks if the number is [prime](prime.md) along the way. (Note that we'll do it in a naive, educational way -- it can be done better). Let's start by writing the steps in plain [English](english.md):
|
||||
Let's write a simple algorithm that counts the number of divisors of given number *x* and checks if the number is [prime](prime.md) along the way. (Note that we'll do it in a [naive](naive.md), educational way -- it can be done better). Let's start by writing the steps in plain [English](english.md) (sometimes called [pseudocode](pseudocode.md)):
|
||||
|
||||
1. Read the number *x* from the input.
|
||||
2. Set the *divisor counter* to 0.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue