Add primality tests.

This commit is contained in:
Oleksii Trekhleb 2018-04-17 08:02:06 +03:00
parent 54f6aadec4
commit 4fc5483892
4 changed files with 107 additions and 2 deletions

View File

@ -31,10 +31,10 @@
* [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci)
* [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/cartesian-product)
* [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/power-set)
* [Primality Test](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test)
* [Primality Test](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test) (Trial Division)
* [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the greatest common divisor (GCD)
* Collatz Conjecture algorithm
* Extended Euclidean algorithm
* Euclidean algorithm to calculate the Greatest Common Divisor (GCD)
* Find Divisors
* Fisher-Yates
* Greatest Difference

View File

@ -0,0 +1,57 @@
# Euclidean algorithm
In mathematics, the Euclidean algorithm, or Euclid's algorithm,
is an efficient method for computing the greatest common divisor
(GCD) of two numbers, the largest number that divides both of
them without leaving a remainder.
The Euclidean algorithm is based on the principle that the
greatest common divisor of two numbers does not change if
the larger number is replaced by its difference with the
smaller number. For example, `21` is the GCD of `252` and
`105` (as `252 = 21 × 12` and `105 = 21 × 5`), and the same
number `21` is also the GCD of `105` and `252 105 = 147`.
Since this replacement reduces the larger of the two numbers,
repeating this process gives successively smaller pairs of
numbers until the two numbers become equal.
When that occurs, they are the GCD of the original two numbers.
By reversing the steps, the GCD can be expressed as a sum of
the two original numbers each multiplied by a positive or
negative integer, e.g., `21 = 5 × 105 + (2) × 252`.
The fact that the GCD can always be expressed in this way is
known as Bézout's identity.
![GCD](https://upload.wikimedia.org/wikipedia/commons/3/37/Euclid%27s_algorithm_Book_VII_Proposition_2_3.png)
Euclid's method for finding the greatest common divisor (GCD)
of two starting lengths `BA` and `DC`, both defined to be
multiples of a common "unit" length. The length `DC` being
shorter, it is used to "measure" `BA`, but only once because
remainder `EA` is less than `DC`. EA now measures (twice)
the shorter length `DC`, with remainder `FC` shorter than `EA`.
Then `FC` measures (three times) length `EA`. Because there is
no remainder, the process ends with `FC` being the `GCD`.
On the right Nicomachus' example with numbers `49` and `21`
resulting in their GCD of `7` (derived from Heath 1908:300).
![GCD](https://upload.wikimedia.org/wikipedia/commons/7/74/24x60.svg)
A `24-by-60` rectangle is covered with ten `12-by-12` square
tiles, where `12` is the GCD of `24` and `60`. More generally,
an `a-by-b` rectangle can be covered with square tiles of
side-length `c` only if `c` is a common divisor of `a` and `b`.
![GCD](https://upload.wikimedia.org/wikipedia/commons/1/1c/Euclidean_algorithm_1071_462.gif)
Subtraction-based animation of the Euclidean algorithm.
The initial rectangle has dimensions `a = 1071` and `b = 462`.
Squares of size `462×462` are placed within it leaving a
`462×147` rectangle. This rectangle is tiled with `147×147`
squares until a `21×147` rectangle is left, which in turn is
tiled with `21×21` squares, leaving no uncovered area.
The smallest square size, `21`, is the GCD of `1071` and `462`.
## References
[Wikipedia](https://en.wikipedia.org/wiki/Euclidean_algorithm)

View File

@ -0,0 +1,24 @@
import euclideanAlgorithm from '../euclideanAlgorithm';
describe('euclideanAlgorithm', () => {
it('should calculate GCD', () => {
expect(euclideanAlgorithm(0, 0)).toBeNull();
expect(euclideanAlgorithm(2, 0)).toBe(2);
expect(euclideanAlgorithm(0, 2)).toBe(2);
expect(euclideanAlgorithm(1, 2)).toBe(1);
expect(euclideanAlgorithm(2, 1)).toBe(1);
expect(euclideanAlgorithm(6, 6)).toBe(6);
expect(euclideanAlgorithm(2, 4)).toBe(2);
expect(euclideanAlgorithm(4, 2)).toBe(2);
expect(euclideanAlgorithm(12, 4)).toBe(4);
expect(euclideanAlgorithm(4, 12)).toBe(4);
expect(euclideanAlgorithm(5, 13)).toBe(1);
expect(euclideanAlgorithm(27, 13)).toBe(1);
expect(euclideanAlgorithm(24, 60)).toBe(12);
expect(euclideanAlgorithm(60, 24)).toBe(12);
expect(euclideanAlgorithm(252, 105)).toBe(21);
expect(euclideanAlgorithm(105, 252)).toBe(21);
expect(euclideanAlgorithm(1071, 462)).toBe(21);
expect(euclideanAlgorithm(462, 1071)).toBe(21);
});
});

View File

@ -0,0 +1,24 @@
/**
* @param {number} a
* @param {number} b
* @return {number|null}
*/
export default function euclideanAlgorithm(a, b) {
if (a === 0 && b === 0) {
return null;
}
if (a === 0 && b !== 0) {
return b;
}
if (a !== 0 && b === 0) {
return a;
}
if (a > b) {
return euclideanAlgorithm(a - b, b);
}
return euclideanAlgorithm(b - a, a);
}