From 42b5a462b7681d1f61c94972fd01dfb610d7c94a Mon Sep 17 00:00:00 2001 From: appleJax Date: Tue, 4 Sep 2018 15:03:29 -0500 Subject: [PATCH 1/4] add karatsuba multiplication algorithm --- .../math/karatsuba-multiplication/README.md | 0 .../__test__/karatsuba.test.js | 7 ++ .../karatsuba-multiplication/karatsuba.js | 66 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/algorithms/math/karatsuba-multiplication/README.md create mode 100644 src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js create mode 100644 src/algorithms/math/karatsuba-multiplication/karatsuba.js diff --git a/src/algorithms/math/karatsuba-multiplication/README.md b/src/algorithms/math/karatsuba-multiplication/README.md new file mode 100644 index 00000000..e69de29b diff --git a/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js b/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js new file mode 100644 index 00000000..86157d58 --- /dev/null +++ b/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js @@ -0,0 +1,7 @@ +import karatsuba from '../karatsuba'; + +describe('karatsuba multiplication', () => { + xit('should multiply numbers correctly', () => { + expect(karatsuba(1234, 5678)).toEqual(7006652); + }); +}); diff --git a/src/algorithms/math/karatsuba-multiplication/karatsuba.js b/src/algorithms/math/karatsuba-multiplication/karatsuba.js new file mode 100644 index 00000000..de6e171d --- /dev/null +++ b/src/algorithms/math/karatsuba-multiplication/karatsuba.js @@ -0,0 +1,66 @@ +/** + * + * @param {number} x + * @param {number} y + * @return {number} + */ +export default function karatsuba(x, y) { + // BASE CASE: + // if numbers are sufficiently small, + // multiply them together in the traditional way + if (x < 10 || y < 10) { + return x * y; + } + + const minDigits = Math.min( + String(x).length, + String(y).length, + ); + + // scaleFactor is used to split the numbers + // into smaller numbers for recursion. + // when combining the subcomputations back + // together, the scaleFactor is used to + // recreate the components of the original number + const scaleFactor = 10 ** Math.floor(minDigits / 2); + + // a b are the two components of x + // c d are the two components of y + // + // e.g. + // x = 1234 -> a = 12, b = 34 + // y = 5678 -> c = 56, d = 78 + // + // example of component computations: + // x = 1234, y = 5678 + // scaleFactor = 100 + // a = floor(1234 / 100) = floor(12.34) = 12 + const a = Math.floor(x / scaleFactor); + + // b = 1234 - (12 * 100) = 1234 - 1200 = 34 + const b = x - (a * scaleFactor); + + // c = floor(5678 / 100) = floor(56.78) = 56 + const c = Math.floor(y / scaleFactor); + + // d = 5678 - (56 * 100) = 5678 - 5600 = 78 + const d = y - (c * scaleFactor); + + // compute sub-expressions: + // since a + b is less than x, and c + d is less than y + // the recursion is guaranteed to reach the base case + const ac = karatsuba(a, c); + const bd = karatsuba(b, d); + const abcd = karatsuba(a + b, c + d); + + // combine sub-expressions: + // since the scaleFactor was used to + // artificially reduce the size of the components, + // the scaleFactor must be applied in reverse + // to reconstruct the original components + const A = ac * (scaleFactor ** 2); + const B = (abcd - ac - bd) * scaleFactor; + const C = bd; + + return A + B + C; +} From 4b67f1e158e33f53d0d729bc3bbd3e551ed0c92f Mon Sep 17 00:00:00 2001 From: appleJax Date: Mon, 15 Oct 2018 21:20:05 -0500 Subject: [PATCH 2/4] add partial README --- .../math/karatsuba-multiplication/README.md | 7 ++++++ .../__test__/karatsuba.test.js | 9 ++++++- .../karatsuba-multiplication/karatsuba.js | 24 ++++++++++--------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/algorithms/math/karatsuba-multiplication/README.md b/src/algorithms/math/karatsuba-multiplication/README.md index e69de29b..d542396c 100644 --- a/src/algorithms/math/karatsuba-multiplication/README.md +++ b/src/algorithms/math/karatsuba-multiplication/README.md @@ -0,0 +1,7 @@ +# Karatsuba Multiplication + +Karatsuba is a fast multiplication algorithm discovered by Anatoly Karatsuba in 1960. Given two n-digit numbers, the "grade-school" method of long multiplication has a time complexity of O(n2), whereas the karatsuba algorithm has a time complexity of O(n1.59). + +## References +[Stanford Algorithms (YouTube)](https://www.youtube.com/watch?v=JCbZayFr9RE) +[Wikipedia](https://en.wikipedia.org/wiki/Karatsuba_algorithm) \ No newline at end of file diff --git a/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js b/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js index 86157d58..7a4979d6 100644 --- a/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js +++ b/src/algorithms/math/karatsuba-multiplication/__test__/karatsuba.test.js @@ -1,7 +1,14 @@ import karatsuba from '../karatsuba'; describe('karatsuba multiplication', () => { - xit('should multiply numbers correctly', () => { + it('should multiply simple numbers correctly', () => { + expect(karatsuba(0, 37)).toEqual(0); + expect(karatsuba(1, 8)).toEqual(8); + expect(karatsuba(5, 6)).toEqual(30); + }); + + it('should multiply larger numbers correctly', () => { expect(karatsuba(1234, 5678)).toEqual(7006652); + expect(karatsuba(9182734, 726354172)).toEqual(6669917151266248); }); }); diff --git a/src/algorithms/math/karatsuba-multiplication/karatsuba.js b/src/algorithms/math/karatsuba-multiplication/karatsuba.js index de6e171d..67ea1510 100644 --- a/src/algorithms/math/karatsuba-multiplication/karatsuba.js +++ b/src/algorithms/math/karatsuba-multiplication/karatsuba.js @@ -12,28 +12,30 @@ export default function karatsuba(x, y) { return x * y; } - const minDigits = Math.min( - String(x).length, - String(y).length, - ); - + // SCALE FACTOR: // scaleFactor is used to split the numbers // into smaller numbers for recursion. // when combining the subcomputations back // together, the scaleFactor is used to - // recreate the components of the original number + // recreate the magnitude of the original numbers + const minDigits = Math.min( + String(x).length, + String(y).length, + ); const scaleFactor = 10 ** Math.floor(minDigits / 2); + // PARAMETER COMPONENTS: // a b are the two components of x // c d are the two components of y // // e.g. // x = 1234 -> a = 12, b = 34 // y = 5678 -> c = 56, d = 78 - // + // example of component computations: // x = 1234, y = 5678 // scaleFactor = 100 + // a = floor(1234 / 100) = floor(12.34) = 12 const a = Math.floor(x / scaleFactor); @@ -46,18 +48,18 @@ export default function karatsuba(x, y) { // d = 5678 - (56 * 100) = 5678 - 5600 = 78 const d = y - (c * scaleFactor); - // compute sub-expressions: + // COMPUTE SUB-EXPRESSIONS: // since a + b is less than x, and c + d is less than y // the recursion is guaranteed to reach the base case const ac = karatsuba(a, c); const bd = karatsuba(b, d); const abcd = karatsuba(a + b, c + d); - // combine sub-expressions: + // COMBINE SUB-EXPRESSIONS: // since the scaleFactor was used to - // artificially reduce the size of the components, + // reduce the size of the components, // the scaleFactor must be applied in reverse - // to reconstruct the original components + // to reconstruct the magnitude of the original components const A = ac * (scaleFactor ** 2); const B = (abcd - ac - bd) * scaleFactor; const C = bd; From 0cdb6b3798a369f47eb843235a848ff416605a93 Mon Sep 17 00:00:00 2001 From: appleJax Date: Mon, 15 Oct 2018 22:20:44 -0500 Subject: [PATCH 3/4] finish README --- .../math/karatsuba-multiplication/README.md | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/algorithms/math/karatsuba-multiplication/README.md b/src/algorithms/math/karatsuba-multiplication/README.md index d542396c..ba2457f5 100644 --- a/src/algorithms/math/karatsuba-multiplication/README.md +++ b/src/algorithms/math/karatsuba-multiplication/README.md @@ -2,6 +2,40 @@ Karatsuba is a fast multiplication algorithm discovered by Anatoly Karatsuba in 1960. Given two n-digit numbers, the "grade-school" method of long multiplication has a time complexity of O(n2), whereas the karatsuba algorithm has a time complexity of O(n1.59). +## Recursive Formula + +``` +x = 1234 +y = 5678 + +karatsuba(x, y) +``` + +1. Split each number into numbers with half as many digits +``` +a = 12 +b = 34 + +c = 56 +d = 78 +``` + +2. Compute 3 subexpressions from the smaller numbers + - `ac = a * c` + - `bd = b * d` + - `abcd = (a + b) * (c + d)` + +3. Combine subexpressions to calculate the product +``` +A = ac * 1000 +B = (abcd - ac - bd) * 100 +C = bd + +x * y = A + B + C +``` + +_**Note:**_ *The karatsuba algorithm can be applied recursively to calculate each product in the subexpressions.* (`a * c = karatsuba(a, c)`*). When the numbers get smaller than some arbitrary threshold, they are multiplied in the traditional way.* + ## References [Stanford Algorithms (YouTube)](https://www.youtube.com/watch?v=JCbZayFr9RE) -[Wikipedia](https://en.wikipedia.org/wiki/Karatsuba_algorithm) \ No newline at end of file +[Wikipedia](https://en.wikipedia.org/wiki/Karatsuba_algorithm) From c4eead424ab042441a662a62b91f516aa0da1a10 Mon Sep 17 00:00:00 2001 From: appleJax Date: Tue, 16 Oct 2018 13:43:28 -0500 Subject: [PATCH 4/4] fix typos --- src/algorithms/math/karatsuba-multiplication/README.md | 2 +- src/algorithms/math/karatsuba-multiplication/karatsuba.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/algorithms/math/karatsuba-multiplication/README.md b/src/algorithms/math/karatsuba-multiplication/README.md index ba2457f5..94ea9308 100644 --- a/src/algorithms/math/karatsuba-multiplication/README.md +++ b/src/algorithms/math/karatsuba-multiplication/README.md @@ -27,7 +27,7 @@ d = 78 3. Combine subexpressions to calculate the product ``` -A = ac * 1000 +A = ac * 10000 B = (abcd - ac - bd) * 100 C = bd diff --git a/src/algorithms/math/karatsuba-multiplication/karatsuba.js b/src/algorithms/math/karatsuba-multiplication/karatsuba.js index 67ea1510..f0da5194 100644 --- a/src/algorithms/math/karatsuba-multiplication/karatsuba.js +++ b/src/algorithms/math/karatsuba-multiplication/karatsuba.js @@ -15,7 +15,7 @@ export default function karatsuba(x, y) { // SCALE FACTOR: // scaleFactor is used to split the numbers // into smaller numbers for recursion. - // when combining the subcomputations back + // when combining the subexpressions back // together, the scaleFactor is used to // recreate the magnitude of the original numbers const minDigits = Math.min( @@ -48,14 +48,14 @@ export default function karatsuba(x, y) { // d = 5678 - (56 * 100) = 5678 - 5600 = 78 const d = y - (c * scaleFactor); - // COMPUTE SUB-EXPRESSIONS: + // COMPUTE SUBEXPRESSIONS: // since a + b is less than x, and c + d is less than y // the recursion is guaranteed to reach the base case const ac = karatsuba(a, c); const bd = karatsuba(b, d); const abcd = karatsuba(a + b, c + d); - // COMBINE SUB-EXPRESSIONS: + // COMBINE SUBEXPRESSIONS: // since the scaleFactor was used to // reduce the size of the components, // the scaleFactor must be applied in reverse