This commit is contained in:
Oleksii Trekhleb 2018-04-17 09:28:15 +03:00
parent 34522c8087
commit 91457191b1
6 changed files with 111 additions and 7 deletions

View File

@ -33,10 +33,9 @@
* [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) (trial division)
* [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the greatest common divisor (GCD)
* [Least Common Multiple (LCM)](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple)
* [FisherYates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fisher-yates) - random permutation of a finite sequence
* Collatz Conjecture algorithm
* Greatest Difference
* Least Common Multiple
* Newton's square
* Shannon Entropy
* **String**

View File

@ -20,5 +20,7 @@ describe('euclideanAlgorithm', () => {
expect(euclideanAlgorithm(105, 252)).toBe(21);
expect(euclideanAlgorithm(1071, 462)).toBe(21);
expect(euclideanAlgorithm(462, 1071)).toBe(21);
expect(euclideanAlgorithm(462, -1071)).toBe(21);
expect(euclideanAlgorithm(-462, -1071)).toBe(21);
});
});

View File

@ -1,9 +1,12 @@
/**
* @param {number} a
* @param {number} b
* @param {number} originalA
* @param {number} originalB
* @return {number|null}
*/
export default function euclideanAlgorithm(a, b) {
export default function euclideanAlgorithm(originalA, originalB) {
const a = Math.abs(originalA);
const b = Math.abs(originalB);
if (a === 0 && b === 0) {
return null;
}
@ -16,9 +19,14 @@ export default function euclideanAlgorithm(a, b) {
return a;
}
// Normally we need to do subtraction (a - b) but to prevent
// recursion occurs to often we may shorten subtraction to (a % b).
// Since (a % b) is normally means that we've subtracted b from a
// many times until the difference became less then a.
if (a > b) {
return euclideanAlgorithm(a - b, b);
return euclideanAlgorithm(a % b, b);
}
return euclideanAlgorithm(b - a, a);
return euclideanAlgorithm(b % a, a);
}

View File

@ -0,0 +1,62 @@
# Least common multiple
In arithmetic and number theory, the least common multiple,
lowest common multiple, or smallest common multiple of
two integers `a` and `b`, usually denoted by `LCM(a, b)`, is
the smallest positive integer that is divisible by
both `a` and `b`. Since division of integers by zero is
undefined, this definition has meaning only if `a` and `b` are
both different from zero. However, some authors define `lcm(a,0)`
as `0` for all `a`, which is the result of taking the `lcm`
to be the least upper bound in the lattice of divisibility.
## Example
What is the LCM of 4 and 6?
Multiples of `4` are:
```
4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, ...
```
and the multiples of `6` are:
```
6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, ...
```
Common multiples of `4` and `6` are simply the numbers
that are in both lists:
```
12, 24, 36, 48, 60, 72, ....
```
So, from this list of the first few common multiples of
the numbers `4` and `6`, their least common multiple is `12`.
## Computing the least common multiple
The following formula reduces the problem of computing the
least common multiple to the problem of computing the greatest
common divisor (GCD), also known as the greatest common factor:
```
lcm(a, b) = |a * b| / gcd(a, b)
```
![LCM](https://upload.wikimedia.org/wikipedia/commons/c/c9/Symmetrical_5-set_Venn_diagram_LCM_2_3_4_5_7.svg)
A Venn diagram showing the least common multiples of
combinations of `2`, `3`, `4`, `5` and `7` (`6` is skipped as
it is `2 × 3`, both of which are already represented).
For example, a card game which requires its cards to be
divided equally among up to `5` players requires at least `60`
cards, the number at the intersection of the `2`, `3`, `4`
and `5` sets, but not the `7` set.
## References
[Wikipedia](https://en.wikipedia.org/wiki/Least_common_multiple)

View File

@ -0,0 +1,18 @@
import leastCommonMultiple from '../leastCommonMultiple';
describe('leastCommonMultiple', () => {
it('should find least common multiple', () => {
expect(leastCommonMultiple(0, 0)).toBe(0);
expect(leastCommonMultiple(1, 0)).toBe(0);
expect(leastCommonMultiple(0, 1)).toBe(0);
expect(leastCommonMultiple(4, 6)).toBe(12);
expect(leastCommonMultiple(6, 21)).toBe(42);
expect(leastCommonMultiple(7, 2)).toBe(14);
expect(leastCommonMultiple(3, 5)).toBe(15);
expect(leastCommonMultiple(7, 3)).toBe(21);
expect(leastCommonMultiple(1000000, 2)).toBe(1000000);
expect(leastCommonMultiple(-9, -18)).toBe(18);
expect(leastCommonMultiple(-7, -9)).toBe(63);
expect(leastCommonMultiple(-7, 9)).toBe(63);
});
});

View File

@ -0,0 +1,15 @@
import euclideanAlgorithm from '../euclidean-algorithm/euclideanAlgorithm';
/**
* @param {number} a
* @param {number} b
* @return {number}
*/
export default function leastCommonMultiple(a, b) {
if (a === 0 && b === 0) {
return 0;
}
return Math.abs(a * b) / euclideanAlgorithm(a, b);
}