less_retarded_wiki/algorithm.md
2022-11-28 20:07:33 +01:00

182 lines
11 KiB
Markdown

# Algorithm
Algorithm is an exact description of how to solve a problem. Algorithms are basically what [programming](programming.md) is all about: we tell computers, 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.
Cooking recipes are sometimes given as an example of a non-computer algorithm. The so called wall-follower is a simple algorithm to get out of any maze: you just pick either a left-hand or right-hand wall and then keep following it. You may write a crazy algorithm for how to survive in a jungle, but it has to be **exact**; if there is any ambiguity, it is not considered an algorithm.
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).
Algorithms are mostly (possibly [not always](declarative.md), depending on definitions) 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"). These jumps can be used to create **[branches](branch.md)** (in programming known as *if-then-else*) and **[loops](loop.md)** (these two constructs are known as [control structures](control_structure.md) -- they don't express an action but control where we move in the algorithm itself). All in all, **any algorithm can be written with only these three constructs**:
- **sequence**: A series of steps, one after another.
- **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.").
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.
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) or [switch](switch.md) statements (selection but with more than two branches). Loops are also commonly divided into several types: counted loops, loops with condition and the beginning and loops with condition at the end (`for`, `while` and `do while` in [C](c.md), respectively). Similarly to mathematical equations, algorithms make use of [variables](variable.md), i.e. values which can change that have a specific name (such as *x* or *myVariable*).
[Flowcharts](flowchart.md) are a way of visually expressing algorithms, you have probably seen some. [Decision trees](decision_tree.md) are special cases of algorithms that have no loops, you have probably seen some too. Even though some languages (mostly educational such as [Snap](snap.md)) are visual and similar to flow charts, it is not practical to create big algorithms in this way -- serious programs are written as a text in [programming languages](programming_language.md).
## Example
Let's write a simple algorithm that counts the number of divisors of given number *x* and check 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):
1. Read the number *x* from the input.
2. Set the *divisor counter* to 0.
3. Set *currently checked number* to 1.
4. While *currently checked number* is lower or equal than *x*:
- a: If *currently checked number* divides *x*, increase *divisor counter* by 1.
- b: Increase *currently checked number*.
5. Write out the *divisor counter*.
6. If *divisor counter* is equal to 2, write out the number is a prime.
Notice that *x*, *divisor counter* and *currently checked number* are [variables](variable.md). Step 4 is a loop (iteration) and steps *a* and 6 are branches (selection). The flowchart of this algorithm is:
```
START
|
V
read x
|
V
set divisor count to 0
|
V
set checked number to 1
|
------------>|
| |
| V no
| checked number <= x ? -------
| | |
| | yes |
| V |
| checked number no |
| divides x ? -------- |
| | | |
| | yes | |
| V | |
| increase divisor | |
| count by 1 | |
| | | |
| | | |
| |<------------- |
| | |
| V |
| increase checked V
| number by 1 print divisor count
| | |
-------------- |
V no
divisor count = 2 ? ------
| |
| yes |
V |
print "number is prime" |
| |
|<----------------
V
END
```
This algorithm would be written in [Python](python.md) as:
```
x = int(input("enter a number: "))
divisors = 0
for i in range(1,x + 1):
if x % i == 0: # i divides x?
divisors = divisors + 1
print("divisors: " + str(divisors))
if divisors == 2:
print("It is a prime!")
```
and in [C](c.md) as:
```
#include <stdio.h>
int main(void)
{
int x, divisors = 0;
scanf("%d",&x); // read a number
for (int i = 1; i <= x; ++i)
if (x % i == 0) // i divides x?
divisors = divisors + 1;
printf("number of divisors: %d\n",divisors);
if (divisors == 2)
puts("It is a prime!");
return 0;
}
```
## Study of Algorithms
As algorithms are at the heart of [computer science](scompsci.md), there's a lot of rich theory and knowledge about them.
[Turing machine](turing_machine.md), created by [Alan Turing](turing.md), is the traditional formal tool for studying algorithms. From theoretical computer science we know not all problems are [computable](computability.md), i.e. there are problems unsolvable by any algorithm (e.g. the [halting problem](halting_problem.md)). [Computational complexity](computational_complexity.md) is a theoretical study of resource consumption by algorithms, i.e. how fast and memory efficient algorithms are (see e.g. [P vs NP](p_vs_np.md)). [Mathematical programming](mathematical_programming.md) is concerned, besides others, with optimizing algorithms so that their time and/or space complexity is as low as possible which gives rise to algorithm design methods such as [dynamic programming](dynamic_programming.md) ([optimization](optimization.md) is a less theoretical approach to making more efficient algorithms). [Formal verification](formal_verification.md) is a field that tries to mathematically (and sometimes automatically) prove correctness of algorithms (this is needed for critical software, e.g. in planes or medicine). [Genetic programming](generic_programming.md) and some other methods of [artificial intelligence](ai.md) try to automatically create algorithms (*algorithms that create algorithms*). [Quantum computing](quantum.md) is concerned with creating new kind of algorithms algorithms for quantum computers (a new type of still-in-research computers). [Programming language](programming_language.md) design is an art of finding best ways of expressing algorithms.
## Specific Algorithms
Following are some common algorithms classified into groups.
- [graphics](graphics.md)
- [DDA](dda.md): line drawing algorithm
- [flood fill](flood_fille.md)
- [FXAA](fxaa.md)
- [Hough transform](hough_transform.md): finds shapes in pictures
- [painter's algorithm](painters_algorithm.md)
- [path tracing](path_tracing.md)
- [ray tracing](ray_tracing.md)
- [math](math.md)
- [Boot'h algorithm](booths_algorithm.md): algorithm for multiplication
- [Dijkstra's algorithm](dijkstras_algorithm.md)
- [Euclidean algorithm](euclidean_algorithm.md): computes greatest common divisor
- [numerical algorithms](numerical.md): approximate mathematical functions
- [sieve of Eratosthenes](sieve_of_eratosthenes.md): computes [prime numbers](prime.md)
- [sorting](sorting.md)
- [bogosort](bogosort.md) (stupid sort)
- [bubble sort](bubble_sort.md): simple, kind of slow but still usable sorting algorithm
- [heap sort](heap_sort.md)
- [insertion sort](insertion_sort.md)
- [merge sort](merge_sort.md)
- [shaker sort](shaker_sort.md)
- [selection sort](selection_sort.md)
- [slow sort](slow_sort.md)
- [quick sort](quick_sort.md): one of the fastest sorting algorithms
- [searching](searching.md)
- [binary search](binary_search.md)
- [linear search](linear_search.md)
- [other](other.md)
- [A*](a_start.md): path searching algorithm, used by [AI](ai.md) in many [games](game.md)
- [backpropagation](backpropagation.md)
- [fizzbuzz](fizzbuzz.md): problem/simple algorithm given in job interviews to filter out complete [noobs](noob.md)
- [FFT](fft.md): quickly converts signal (audio, image, ...) to its representation in frequencies, one of the most famous and important algorithms
- [Huffman coding](huffman_code.md): [compression](compression.md) algorithm
- [Kalman filter](kalman_filter.md)
- [k-means](k_means.md): [clustering](clustering.md) algorithm
- [MD5](md5.md): [hash](hash.md) function
- [minimax](minimax.md) plus [alpha-beta pruning](alpha_beta.md): used by many [AI](ai.md)s that play turn based games
- [proof of work](proof_of_work.md) algorithms: used by some [cryptocurrencies](crypto.md)
- [RSA](rsa.md)
- [Shor's algorithm](shors_algorithm.md): [quantum](quantum.md) factorization algorithm
- [YouTube](youtube.md) algorithm: secret algorithm YouTube uses to suggest videos to viewers, a lot of people hate it :)
## See Also
- [programming](programming.md)
- [design pattern](design_pattern.md)
- [recursion](recursion.md)