diff --git a/README.md b/README.md index 915b3fb38e..a62984fb7c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ a set of rules that precisely define a sequence of operations. * **Math** * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two, make negative etc. * `B` [Factorial](src/algorithms/math/factorial) + * `B` [nth Root](src/algorithms/math/nth-root) + * `B` [Extended Euclidean Algorithm](src/algorithms/math/extended-euclidean-algorithm) * `B` [Fibonacci Number](src/algorithms/math/fibonacci) * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) * `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) diff --git a/src/algorithms/math/bits/__test__/isEven.test.js b/src/algorithms/math/bits/__test__/isEven.test.js new file mode 100644 index 0000000000..d9f6946526 --- /dev/null +++ b/src/algorithms/math/bits/__test__/isEven.test.js @@ -0,0 +1,19 @@ +import isEven from '../isEven'; + +describe('isEven', () => { + it('should get if number is even', () => { + expect(isEven(2)).toBe(true); + expect(isEven(6)).toBe(true); + expect(isEven(8)).toBe(true); + expect(isEven(10)).toBe(true); + expect(isEven(12)).toBe(true); + }); + + it('should get if number is odd', () => { + expect(isEven(3)).toBe(false); + expect(isEven(5)).toBe(false); + expect(isEven(7)).toBe(false); + expect(isEven(9)).toBe(false); + expect(isEven(11)).toBe(false); + }); +}); diff --git a/src/algorithms/math/bits/countSetBits.js b/src/algorithms/math/bits/countSetBits.js index 6e24eebf26..f054ac03fa 100644 --- a/src/algorithms/math/bits/countSetBits.js +++ b/src/algorithms/math/bits/countSetBits.js @@ -7,11 +7,10 @@ export default function countSetBits(originalNumber) { let number = originalNumber; while (number) { - // Add last bit of the number to the sum of set bits. - setBitsCount += number & 1; + // Using And operation on number with previous number. + number &= (number - 1); - // Shift number right by one bit to investigate other bits. - number >>= 1; + setBitsCount += 1; } return setBitsCount; diff --git a/src/algorithms/math/bits/isEven.js b/src/algorithms/math/bits/isEven.js new file mode 100644 index 0000000000..2bbb9e587c --- /dev/null +++ b/src/algorithms/math/bits/isEven.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return {Boolean} + */ +export default function isEven(number) { + return ((number & 1) === 0); +} diff --git a/src/algorithms/math/extended-euclidean-algorithm/README.MD b/src/algorithms/math/extended-euclidean-algorithm/README.MD new file mode 100644 index 0000000000..24f9c654bb --- /dev/null +++ b/src/algorithms/math/extended-euclidean-algorithm/README.MD @@ -0,0 +1,14 @@ +# Extended Euclidean algorithm + +In arithmetic and computer programming, the extended Euclidean algorithm is an extension to the Euclidean algorithm, +and computes, in addition to the greatest common divisor of integers a and b, also the coefficients of Bézout's +identity, which are integers x and y such that `ax + by = gcd(a,b)`. +This is a certifying algorithm, because the gcd is the only number that can simultaneously satisfy this equation and +divide the inputs. It allows one to compute also, with almost no extra cost, the quotients of a and b by their +greatest common divisor. + + + +## References + +[Wikipedia](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm) diff --git a/src/algorithms/math/extended-euclidean-algorithm/__test__/extendedEuclid.test.js b/src/algorithms/math/extended-euclidean-algorithm/__test__/extendedEuclid.test.js new file mode 100644 index 0000000000..967876c954 --- /dev/null +++ b/src/algorithms/math/extended-euclidean-algorithm/__test__/extendedEuclid.test.js @@ -0,0 +1,23 @@ +import extendedEuclid from '../extendedEuclid'; + +describe('extendedEuclideanAlgorithm', () => { + it('should calculate coefficients', () => { + expect(extendedEuclid(30, 20)).toEqual({ + gcd: 10, + x: 1, + y: -1, + }); + + expect(extendedEuclid(30, 50)).toEqual({ + gcd: 10, + x: 2, + y: -1, + }); + + expect(extendedEuclid(65, 40)).toEqual({ + gcd: 5, + x: -3, + y: 5, + }); + }); +}); diff --git a/src/algorithms/math/extended-euclidean-algorithm/extendedEuclid.js b/src/algorithms/math/extended-euclidean-algorithm/extendedEuclid.js new file mode 100644 index 0000000000..912c9c3607 --- /dev/null +++ b/src/algorithms/math/extended-euclidean-algorithm/extendedEuclid.js @@ -0,0 +1,21 @@ +/** + * @param {number} Coefficient A + * @param {number} Coefficient B + * @return {Object} {gcd, x, y} + */ + +export default function extendedEuclid(coeffA, coeffB) { + if (coeffA === 0) { + return { + gcd: coeffB, + x: 0, + y: 1, + }; + } + const variables = extendedEuclid(coeffB % coeffA, coeffA); + return { + gcd: variables.gcd, + x: (variables.y - Math.floor(coeffB / coeffA) * variables.x), + y: variables.x, + }; +} diff --git a/src/algorithms/math/nth-root/README.MD b/src/algorithms/math/nth-root/README.MD new file mode 100644 index 0000000000..2a371a9fbd --- /dev/null +++ b/src/algorithms/math/nth-root/README.MD @@ -0,0 +1,8 @@ +# Nth Power using Binary Search + +In computer science, `binary search`, also known as `half-interval search`, `logarithmic search`, or `binary chop`,is a search algorithm that finds the position of a target value within a range or sorted array. Binary search compares the target value to the middle element of the range or array. If they are not equal, the half in which the target cannot lie is eliminated and the search continues on the remaining half, again taking the middle element to compare to the target value, and repeating this until the target value is found. If the search ends with the remaining half being empty, the target is not in the array. Even though the idea is simple, implementing binary search correctly requires attention to some subtleties about its exit conditions and midpoint calculation. + + + +## References +- [Wikipedia](https://en.wikipedia.org/wiki/Binary_search_algorithm) \ No newline at end of file diff --git a/src/algorithms/math/nth-root/__test__/nthRoot.test.js b/src/algorithms/math/nth-root/__test__/nthRoot.test.js new file mode 100644 index 0000000000..987b6d9ba2 --- /dev/null +++ b/src/algorithms/math/nth-root/__test__/nthRoot.test.js @@ -0,0 +1,12 @@ +import nthRoot from '../nthRoot'; + +describe('nth Root', () => { + it('should nth root of number', () => { + expect(nthRoot(2, 2)).toBeCloseTo(1.414213562373095); + expect(nthRoot(2, 3)).toBeCloseTo(1.259921049894873); + expect(nthRoot(2, 4)).toBeCloseTo(1.189207115); + expect(nthRoot(2, 5)).toBeCloseTo(1.148698354997035); + expect(nthRoot(2, 6)).toBeCloseTo(1.122462048309373); + expect(nthRoot(2, 7)).toBeCloseTo(1.104089513673812); + }); +}); diff --git a/src/algorithms/math/nth-root/nthRoot.js b/src/algorithms/math/nth-root/nthRoot.js new file mode 100644 index 0000000000..584673a30e --- /dev/null +++ b/src/algorithms/math/nth-root/nthRoot.js @@ -0,0 +1,32 @@ +/** + * @param {number} num + * @param {number} power + * @return {number} + */ + +export default function nthRoot(num, power) { + const E = 0.000000001; + const roundToMargin = (x) => { + return Math.round(x / E) * E; + }; + + let guess; + const calculateError = () => Math.abs(num - (guess ** power)); + + let start = 0; + let end = num; + let error = 1; + + while (error > E) { + guess = (start + end) / 2; + error = calculateError(); + + if (guess ** power > num) { + end = guess; + } else { + start = guess; + } + } + + return roundToMargin(guess); +}