From fe56f54f820be09a1d12a28b9b7a509fd32f5fc3 Mon Sep 17 00:00:00 2001 From: VinWare <28603906+VinWare@users.noreply.github.com> Date: Thu, 21 Oct 2021 14:58:12 +0530 Subject: [PATCH 1/4] Added Extended Euclidean Algorithm (ExtendedEuclideanGCD.js) to Maths folder, along with relevant test --- Maths/ExtendedEuclideanGCD.js | 60 +++++++++++++++++++++++++ Maths/test/ExtendedEuclideanGCD.test.js | 16 +++++++ 2 files changed, 76 insertions(+) create mode 100644 Maths/ExtendedEuclideanGCD.js create mode 100644 Maths/test/ExtendedEuclideanGCD.test.js diff --git a/Maths/ExtendedEuclideanGCD.js b/Maths/ExtendedEuclideanGCD.js new file mode 100644 index 000000000..9332aa623 --- /dev/null +++ b/Maths/ExtendedEuclideanGCD.js @@ -0,0 +1,60 @@ +/** + * Problem statement and explanation: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm + * + * This algorithm plays an important role for modular arithmetic, and by extension for cyptography algorithms + * + * This implementation uses an iterative approach to calculate + */ + +/** + * + * @param {Number} arg1 first argument + * @param {Number} arg2 second argument + * @returns Array with GCD and first and second Bézout coefficients + */ +const extendedEuclideanGCD = (arg1, arg2) => { + if(typeof arg1 != 'number' || typeof arg2 != 'number') throw new TypeError('Not a Number'); + if(arg1 < 1 || arg2 < 1) throw new TypeError('Must be positive numbers'); + + // Make the order of coefficients correct, as the algorithm assumes r0 > r1 + if (arg1 < arg2) { + const res = extendedEuclideanGCD(arg2,arg1) + const temp = res[1] + res[1] = res[2] + res[2] = temp + return res; + } + + // At this point arg1 > arg2 + + // Remainder values + let r0 = arg1 + let r1 = arg2 + + // Coefficient1 values + let s0 = 1 + let s1 = 0 + + // Coefficient 2 values + let t0 = 0 + let t1 = 1 + + while(r1 != 0) { + const q = Math.floor(r0 / r1); + + const r2 = r0 - r1*q; + const s2 = s0 - s1*q; + const t2 = t0 - t1*q; + + r0 = r1 + r1 = r2 + s0 = s1 + s1 = s2 + t0 = t1 + t1 = t2 + } + return [r0,s0,t0]; +} + +export { extendedEuclideanGCD }; +// ex diff --git a/Maths/test/ExtendedEuclideanGCD.test.js b/Maths/test/ExtendedEuclideanGCD.test.js new file mode 100644 index 000000000..0164fac20 --- /dev/null +++ b/Maths/test/ExtendedEuclideanGCD.test.js @@ -0,0 +1,16 @@ +import { extendedEuclideanGCD } from '../ExtendedEuclideanGCD' + +describe('extendedEuclideanGCD', () => { + it('should return valid values in order for positive arguments', () => { + expect(extendedEuclideanGCD(240, 46)).toMatchObject([2, -9, 47]) + expect(extendedEuclideanGCD(46, 240)).toMatchObject([2, 47, -9]) + }) + it('should give error on non-positive arguments', () => { + expect(() => extendedEuclideanGCD(0,240)).toThrowError(new TypeError('Must be positive numbers')) + expect(() => extendedEuclideanGCD(46,-240)).toThrowError(new TypeError('Must be positive numbers')) + }) + it('should give error on non-numeric arguments', () => { + expect(() => extendedEuclideanGCD('240',46)).toThrowError(new TypeError('Not a Number')); + expect(() => extendedEuclideanGCD([240,46])).toThrowError(new TypeError('Not a Number')); + }) +}) From 5ccfafecbb4b7d6022d597c24c490d12451f7d09 Mon Sep 17 00:00:00 2001 From: VinWare <28603906+VinWare@users.noreply.github.com> Date: Thu, 21 Oct 2021 15:06:33 +0530 Subject: [PATCH 2/4] `npm run style` result --- Dynamic-Programming/MaxProductOfThree.js | 18 +++--- Maths/ExtendedEuclideanGCD.js | 78 ++++++++++++------------ Maths/test/ExtendedEuclideanGCD.test.js | 8 +-- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Dynamic-Programming/MaxProductOfThree.js b/Dynamic-Programming/MaxProductOfThree.js index 1e7ebe3e1..58e5e6362 100644 --- a/Dynamic-Programming/MaxProductOfThree.js +++ b/Dynamic-Programming/MaxProductOfThree.js @@ -5,15 +5,15 @@ * @param {number[]} arrayItems * @returns number */ -export function maxProductOfThree(arrayItems) { +export function maxProductOfThree (arrayItems) { // if size is less than 3, no triplet exists - let n = arrayItems.length + const n = arrayItems.length if (n < 3) throw new Error('Triplet cannot exist with the given array') - let max1 = arrayItems[0], - max2 = -1, - max3 = -1, - min1 = arrayItems[0], - min2 = -1 + let max1 = arrayItems[0] + let max2 = -1 + let max3 = -1 + let min1 = arrayItems[0] + let min2 = -1 for (let i = 1; i < n; i++) { if (arrayItems[i] > max1) { max3 = max2 @@ -32,7 +32,7 @@ export function maxProductOfThree(arrayItems) { min2 = arrayItems[i] } } - let prod1 = max1 * max2 * max3, - prod2 = max1 * min1 * min2 + const prod1 = max1 * max2 * max3 + const prod2 = max1 * min1 * min2 return Math.max(prod1, prod2) } diff --git a/Maths/ExtendedEuclideanGCD.js b/Maths/ExtendedEuclideanGCD.js index 9332aa623..deb0348e8 100644 --- a/Maths/ExtendedEuclideanGCD.js +++ b/Maths/ExtendedEuclideanGCD.js @@ -1,60 +1,60 @@ /** * Problem statement and explanation: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm - * + * * This algorithm plays an important role for modular arithmetic, and by extension for cyptography algorithms - * + * * This implementation uses an iterative approach to calculate */ /** - * + * * @param {Number} arg1 first argument * @param {Number} arg2 second argument * @returns Array with GCD and first and second Bézout coefficients */ const extendedEuclideanGCD = (arg1, arg2) => { - if(typeof arg1 != 'number' || typeof arg2 != 'number') throw new TypeError('Not a Number'); - if(arg1 < 1 || arg2 < 1) throw new TypeError('Must be positive numbers'); + if (typeof arg1 !== 'number' || typeof arg2 !== 'number') throw new TypeError('Not a Number') + if (arg1 < 1 || arg2 < 1) throw new TypeError('Must be positive numbers') - // Make the order of coefficients correct, as the algorithm assumes r0 > r1 - if (arg1 < arg2) { - const res = extendedEuclideanGCD(arg2,arg1) - const temp = res[1] - res[1] = res[2] - res[2] = temp - return res; - } + // Make the order of coefficients correct, as the algorithm assumes r0 > r1 + if (arg1 < arg2) { + const res = extendedEuclideanGCD(arg2, arg1) + const temp = res[1] + res[1] = res[2] + res[2] = temp + return res + } - // At this point arg1 > arg2 + // At this point arg1 > arg2 - // Remainder values - let r0 = arg1 - let r1 = arg2 + // Remainder values + let r0 = arg1 + let r1 = arg2 - // Coefficient1 values - let s0 = 1 - let s1 = 0 + // Coefficient1 values + let s0 = 1 + let s1 = 0 - // Coefficient 2 values - let t0 = 0 - let t1 = 1 - - while(r1 != 0) { - const q = Math.floor(r0 / r1); + // Coefficient 2 values + let t0 = 0 + let t1 = 1 - const r2 = r0 - r1*q; - const s2 = s0 - s1*q; - const t2 = t0 - t1*q; - - r0 = r1 - r1 = r2 - s0 = s1 - s1 = s2 - t0 = t1 - t1 = t2 - } - return [r0,s0,t0]; + while (r1 != 0) { + const q = Math.floor(r0 / r1) + + const r2 = r0 - r1 * q + const s2 = s0 - s1 * q + const t2 = t0 - t1 * q + + r0 = r1 + r1 = r2 + s0 = s1 + s1 = s2 + t0 = t1 + t1 = t2 + } + return [r0, s0, t0] } -export { extendedEuclideanGCD }; +export { extendedEuclideanGCD } // ex diff --git a/Maths/test/ExtendedEuclideanGCD.test.js b/Maths/test/ExtendedEuclideanGCD.test.js index 0164fac20..28acf151c 100644 --- a/Maths/test/ExtendedEuclideanGCD.test.js +++ b/Maths/test/ExtendedEuclideanGCD.test.js @@ -6,11 +6,11 @@ describe('extendedEuclideanGCD', () => { expect(extendedEuclideanGCD(46, 240)).toMatchObject([2, 47, -9]) }) it('should give error on non-positive arguments', () => { - expect(() => extendedEuclideanGCD(0,240)).toThrowError(new TypeError('Must be positive numbers')) - expect(() => extendedEuclideanGCD(46,-240)).toThrowError(new TypeError('Must be positive numbers')) + expect(() => extendedEuclideanGCD(0, 240)).toThrowError(new TypeError('Must be positive numbers')) + expect(() => extendedEuclideanGCD(46, -240)).toThrowError(new TypeError('Must be positive numbers')) }) it('should give error on non-numeric arguments', () => { - expect(() => extendedEuclideanGCD('240',46)).toThrowError(new TypeError('Not a Number')); - expect(() => extendedEuclideanGCD([240,46])).toThrowError(new TypeError('Not a Number')); + expect(() => extendedEuclideanGCD('240', 46)).toThrowError(new TypeError('Not a Number')) + expect(() => extendedEuclideanGCD([240, 46])).toThrowError(new TypeError('Not a Number')) }) }) From 79c7ce45c84907c8c2b4a0ef88c413443c562850 Mon Sep 17 00:00:00 2001 From: VinWare <28603906+VinWare@users.noreply.github.com> Date: Thu, 21 Oct 2021 15:57:20 +0530 Subject: [PATCH 3/4] Fixed `!=` to `!==` and ran `npm run style` --- Conversions/MeterToFeetConversion.js | 6 ++-- .../test/MeterToFeetConversion.test.js | 4 +-- Maths/ExtendedEuclideanGCD.js | 2 +- Maths/FigurateNumber.js | 31 +++++++++---------- Maths/test/FigurateNumber.test.js | 4 +-- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Conversions/MeterToFeetConversion.js b/Conversions/MeterToFeetConversion.js index 13348cd6b..c6094b06b 100644 --- a/Conversions/MeterToFeetConversion.js +++ b/Conversions/MeterToFeetConversion.js @@ -1,10 +1,10 @@ // Foot: https://en.wikipedia.org/wiki/Foot_(unit) const feetToMeter = (feet) => { - return feet*0.3048; + return feet * 0.3048 } const meterToFeet = (meter) => { - return meter/0.3048; + return meter / 0.3048 } -export { feetToMeter, meterToFeet } \ No newline at end of file +export { feetToMeter, meterToFeet } diff --git a/Conversions/test/MeterToFeetConversion.test.js b/Conversions/test/MeterToFeetConversion.test.js index 4951a3593..2258f9741 100644 --- a/Conversions/test/MeterToFeetConversion.test.js +++ b/Conversions/test/MeterToFeetConversion.test.js @@ -1,4 +1,4 @@ -import { meterToFeet, feetToMeter } from "../MeterToFeetConversion"; +import { meterToFeet, feetToMeter } from '../MeterToFeetConversion' describe('Testing conversion of Meter to Feet', () => { it('with feet value', () => { @@ -10,4 +10,4 @@ describe('Testing conversion of Feet to Meter', () => { it('with feet value', () => { expect(feetToMeter(10)).toBe(3.048) }) -}) \ No newline at end of file +}) diff --git a/Maths/ExtendedEuclideanGCD.js b/Maths/ExtendedEuclideanGCD.js index deb0348e8..4e01ea59b 100644 --- a/Maths/ExtendedEuclideanGCD.js +++ b/Maths/ExtendedEuclideanGCD.js @@ -39,7 +39,7 @@ const extendedEuclideanGCD = (arg1, arg2) => { let t0 = 0 let t1 = 1 - while (r1 != 0) { + while (r1 !== 0) { const q = Math.floor(r0 / r1) const r2 = r0 - r1 * q diff --git a/Maths/FigurateNumber.js b/Maths/FigurateNumber.js index 22b8c4bfe..cab8dcefb 100644 --- a/Maths/FigurateNumber.js +++ b/Maths/FigurateNumber.js @@ -1,20 +1,19 @@ /** - Problem Statment and Explanation : + Problem Statment and Explanation : Triangular => https://en.wikipedia.org/wiki/Triangular_number Tetrahedral => https://en.wikipedia.org/wiki/Tetrahedral_number Pentatope => https://en.wikipedia.org/wiki/Pentatope_number - - Example: + Example: Triangular => (0, 1, 3, 6, 10, 15, 21, 28, 36, 45) Tetrahedral => (1, 4, 10, 20, 35, 56, 84, 120, 165,) Pentatope => (1, 5, 15, 35, 70, 126, 210, 330, 495) */ /** - * - * @param {*} number - * @returns + * + * @param {*} number + * @returns */ const isTriangular = (number) => { for (let i = 0; i <= number; i++) { @@ -28,9 +27,9 @@ const isTriangular = (number) => { } /** - * - * @param {*} number - * @returns + * + * @param {*} number + * @returns */ const isTetrahedral = (number) => { for (let i = 1; i <= number; i++) { @@ -43,9 +42,9 @@ const isTetrahedral = (number) => { return false } /** - * - * @param {*} number - * @returns + * + * @param {*} number + * @returns */ const isPentatope = (number) => { for (let i = 1; i <= number; i++) { @@ -59,11 +58,11 @@ const isPentatope = (number) => { } /** - * - * @param {*} number - * @returns + * + * @param {*} number + * @returns */ -let checkAll = (number) => { +const checkAll = (number) => { return { isTriangular: isTriangular(number), isTetrahedral: isTetrahedral(number), diff --git a/Maths/test/FigurateNumber.test.js b/Maths/test/FigurateNumber.test.js index b8b5b1116..7c0055161 100644 --- a/Maths/test/FigurateNumber.test.js +++ b/Maths/test/FigurateNumber.test.js @@ -54,7 +54,7 @@ describe('FigurateNumber', () => { }) /** End */ - it('Check All : should return all true',() => { + it('Check All : should return all true', () => { expect(checkAll(1)).toEqual({ isTriangular: true, isTetrahedral: true, @@ -62,7 +62,7 @@ describe('FigurateNumber', () => { }) }) - it('Check All : should return all true,true,false',() => { + it('Check All : should return all true,true,false', () => { expect(checkAll(15)).toEqual({ isTriangular: true, isTetrahedral: false, From e92e2e39263b57ab589667722655455e3e956982 Mon Sep 17 00:00:00 2001 From: VinWare <28603906+VinWare@users.noreply.github.com> Date: Thu, 21 Oct 2021 18:31:39 +0530 Subject: [PATCH 4/4] Added a short explanation of the Ext Euc Algo --- Maths/ExtendedEuclideanGCD.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Maths/ExtendedEuclideanGCD.js b/Maths/ExtendedEuclideanGCD.js index 4e01ea59b..a5623b18c 100644 --- a/Maths/ExtendedEuclideanGCD.js +++ b/Maths/ExtendedEuclideanGCD.js @@ -2,8 +2,20 @@ * Problem statement and explanation: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm * * This algorithm plays an important role for modular arithmetic, and by extension for cyptography algorithms - * - * This implementation uses an iterative approach to calculate + * + * Basic explanation: + * The Extended Euclidean algorithm is a modification of the standard Euclidean GCD algorithm. + * It allows to calculate coefficients x and y for the equation: + * ax + by = gcd(a,b) + * + * This is called Bézout's identity and the coefficients are called Bézout coefficients + * + * The algorithm uses the Euclidean method of getting remainder: + * r_i+1 = r_i-1 - qi*ri + * and applies it to series s and t (with same quotient q at each stage) + * When r_n reaches 0, the value r_n-1 gives the gcd, and s_n-1 and t_n-1 give the coefficients + * + * This implementation uses an iterative approach to calculate the values */ /** @@ -57,4 +69,3 @@ const extendedEuclideanGCD = (arg1, arg2) => { } export { extendedEuclideanGCD } -// ex