From 76318364c2191c282e2fb351f1b94d9d95a582a5 Mon Sep 17 00:00:00 2001 From: hiitesh1127 Date: Wed, 19 Oct 2022 13:02:59 -0400 Subject: [PATCH 1/3] added-ModularArithmetic-code --- Maths/ModularArithmetic.js | 52 ++++++++++++++++++++++++++++ Maths/test/ModularArithmetic.test.js | 39 +++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 Maths/ModularArithmetic.js create mode 100644 Maths/test/ModularArithmetic.test.js diff --git a/Maths/ModularArithmetic.js b/Maths/ModularArithmetic.js new file mode 100644 index 0000000000..3d2be94e51 --- /dev/null +++ b/Maths/ModularArithmetic.js @@ -0,0 +1,52 @@ +import { extendedEuclideanGCD } from './ExtendedEuclideanGCD' + +/** + * https://brilliant.org/wiki/modular-arithmetic/ + * @param {Number} arg1 first argument + * @param {Number} arg2 second argument + * @returns {Number} + */ + +const MOD = 10000007 + +const isInputValid = (arg1, arg2) => { + if (typeof arg1 !== 'number' || typeof arg2 !== 'number') { + throw new TypeError('Input must be Numbers') + } +} + +/** + * Modulus is Distributive property, + * As a result, we separate it into numbers in order to keep it within MOD's range +*/ + +const add = (arg1, arg2) => { + isInputValid(arg1, arg2) + return ((arg1 % MOD) + (arg2 % MOD)) % MOD +} + +const subtract = (arg1, arg2) => { + isInputValid(arg1, arg2) + // An extra MOD is added to check negative results + return ((arg1 % MOD) - (arg2 % MOD) + MOD) % MOD +} + +const multiply = (arg1, arg2) => { + isInputValid(arg1, arg2) + return ((arg1 % MOD) * (arg2 % MOD)) % MOD +} + +/** + * + * It is not Possible to find Division directly like the above methods, + * So we have to use the Extended Euclidean Theorem for finding Multiplicative Inverse + * https://github.com/TheAlgorithms/JavaScript/blob/master/Maths/ExtendedEuclideanGCD.js + */ + +const divide = (arg1, b) => { + // 1st Index contains the required result + // The theorem may have return Negative value, we need to add MOD to make it Positive + return (extendedEuclideanGCD(arg1, b)[1] + MOD) % MOD +} + +export { add, subtract, multiply, divide } diff --git a/Maths/test/ModularArithmetic.test.js b/Maths/test/ModularArithmetic.test.js new file mode 100644 index 0000000000..1d8ec53ab9 --- /dev/null +++ b/Maths/test/ModularArithmetic.test.js @@ -0,0 +1,39 @@ +import { add, subtract, multiply, divide } from '../ModularArithmetic' + +describe('Modular Arithmetic', () => { + describe('add', () => { + it('Should return 9999993 for 10000000 and 10000000', () => { + expect(add(10000000, 10000000)).toBe(9999993) + }) + it('Should return 9999986 for 10000000 and 20000000', () => { + expect(add(10000000, 20000000)).toBe(9999986) + }) + }) + + describe('subtract', () => { + it('Should return 1000000 for 10000000 and 9000000', () => { + expect(subtract(10000000, 9000000)).toBe(1000000) + }) + it('Should return 7 for 10000000 and 20000000', () => { + expect(subtract(10000000, 20000000)).toBe(7) + }) + }) + + describe('multiply', () => { + it('Should return 1000000 for 100000 and 10000', () => { + expect(multiply(100000, 10000)).toBe(9999307) + }) + it('Should return 7 for 100000 and 10000100', () => { + expect(multiply(10000000, 20000000)).toBe(98) + }) + }) + + describe('divide', () => { + it('Should return 4 for 3 and 11', () => { + expect(divide(3, 11)).toBe(4) + }) + it('Should return 2 for 18 and 7', () => { + expect(divide(18, 7)).toBe(2) + }) + }) +}) From 2acead5ff5580aa2d1c601c797e9cf40f4076bea Mon Sep 17 00:00:00 2001 From: hiitesh1127 Date: Wed, 19 Oct 2022 13:05:28 -0400 Subject: [PATCH 2/3] fix-typo --- Maths/ModularArithmetic.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maths/ModularArithmetic.js b/Maths/ModularArithmetic.js index 3d2be94e51..8b06e57988 100644 --- a/Maths/ModularArithmetic.js +++ b/Maths/ModularArithmetic.js @@ -43,10 +43,10 @@ const multiply = (arg1, arg2) => { * https://github.com/TheAlgorithms/JavaScript/blob/master/Maths/ExtendedEuclideanGCD.js */ -const divide = (arg1, b) => { +const divide = (arg1, arg2) => { // 1st Index contains the required result // The theorem may have return Negative value, we need to add MOD to make it Positive - return (extendedEuclideanGCD(arg1, b)[1] + MOD) % MOD + return (extendedEuclideanGCD(arg1, arg2)[1] + MOD) % MOD } export { add, subtract, multiply, divide } From ec01d3811cc687c9531880c8445f2f42031df8f7 Mon Sep 17 00:00:00 2001 From: hiitesh1127 Date: Wed, 19 Oct 2022 15:30:38 -0400 Subject: [PATCH 3/3] suggested changes --- Maths/ModularArithmetic.js | 78 +++++++++++++++------------- Maths/test/ModularArithmetic.test.js | 24 +++++---- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/Maths/ModularArithmetic.js b/Maths/ModularArithmetic.js index 8b06e57988..26c54ebbb4 100644 --- a/Maths/ModularArithmetic.js +++ b/Maths/ModularArithmetic.js @@ -7,46 +7,50 @@ import { extendedEuclideanGCD } from './ExtendedEuclideanGCD' * @returns {Number} */ -const MOD = 10000007 - -const isInputValid = (arg1, arg2) => { - if (typeof arg1 !== 'number' || typeof arg2 !== 'number') { - throw new TypeError('Input must be Numbers') +export class ModRing { + constructor (MOD) { + this.MOD = MOD } -} - -/** - * Modulus is Distributive property, - * As a result, we separate it into numbers in order to keep it within MOD's range -*/ -const add = (arg1, arg2) => { - isInputValid(arg1, arg2) - return ((arg1 % MOD) + (arg2 % MOD)) % MOD -} - -const subtract = (arg1, arg2) => { - isInputValid(arg1, arg2) - // An extra MOD is added to check negative results - return ((arg1 % MOD) - (arg2 % MOD) + MOD) % MOD -} + isInputValid = (arg1, arg2) => { + if (!this.MOD) { + throw new Error('Modulus must be initialized in the object constructor') + } + if (typeof arg1 !== 'number' || typeof arg2 !== 'number') { + throw new TypeError('Input must be Numbers') + } + } + /** + * Modulus is Distributive property, + * As a result, we separate it into numbers in order to keep it within MOD's range + */ + + add = (arg1, arg2) => { + this.isInputValid(arg1, arg2) + return ((arg1 % this.MOD) + (arg2 % this.MOD)) % this.MOD + } -const multiply = (arg1, arg2) => { - isInputValid(arg1, arg2) - return ((arg1 % MOD) * (arg2 % MOD)) % MOD -} + subtract = (arg1, arg2) => { + this.isInputValid(arg1, arg2) + // An extra MOD is added to check negative results + return ((arg1 % this.MOD) - (arg2 % this.MOD) + this.MOD) % this.MOD + } -/** - * - * It is not Possible to find Division directly like the above methods, - * So we have to use the Extended Euclidean Theorem for finding Multiplicative Inverse - * https://github.com/TheAlgorithms/JavaScript/blob/master/Maths/ExtendedEuclideanGCD.js - */ + multiply = (arg1, arg2) => { + this.isInputValid(arg1, arg2) + return ((arg1 % this.MOD) * (arg2 % this.MOD)) % this.MOD + } -const divide = (arg1, arg2) => { - // 1st Index contains the required result - // The theorem may have return Negative value, we need to add MOD to make it Positive - return (extendedEuclideanGCD(arg1, arg2)[1] + MOD) % MOD + /** + * + * It is not Possible to find Division directly like the above methods, + * So we have to use the Extended Euclidean Theorem for finding Multiplicative Inverse + * https://github.com/TheAlgorithms/JavaScript/blob/master/Maths/ExtendedEuclideanGCD.js + */ + + divide = (arg1, arg2) => { + // 1st Index contains the required result + // The theorem may have return Negative value, we need to add MOD to make it Positive + return (extendedEuclideanGCD(arg1, arg2)[1] + this.MOD) % this.MOD + } } - -export { add, subtract, multiply, divide } diff --git a/Maths/test/ModularArithmetic.test.js b/Maths/test/ModularArithmetic.test.js index 1d8ec53ab9..af42e243de 100644 --- a/Maths/test/ModularArithmetic.test.js +++ b/Maths/test/ModularArithmetic.test.js @@ -1,39 +1,45 @@ -import { add, subtract, multiply, divide } from '../ModularArithmetic' +import { ModRing } from '../ModularArithmetic' describe('Modular Arithmetic', () => { + const MOD = 10000007 + let ring + beforeEach(() => { + ring = new ModRing(MOD) + }) + describe('add', () => { it('Should return 9999993 for 10000000 and 10000000', () => { - expect(add(10000000, 10000000)).toBe(9999993) + expect(ring.add(10000000, 10000000)).toBe(9999993) }) it('Should return 9999986 for 10000000 and 20000000', () => { - expect(add(10000000, 20000000)).toBe(9999986) + expect(ring.add(10000000, 20000000)).toBe(9999986) }) }) describe('subtract', () => { it('Should return 1000000 for 10000000 and 9000000', () => { - expect(subtract(10000000, 9000000)).toBe(1000000) + expect(ring.subtract(10000000, 9000000)).toBe(1000000) }) it('Should return 7 for 10000000 and 20000000', () => { - expect(subtract(10000000, 20000000)).toBe(7) + expect(ring.subtract(10000000, 20000000)).toBe(7) }) }) describe('multiply', () => { it('Should return 1000000 for 100000 and 10000', () => { - expect(multiply(100000, 10000)).toBe(9999307) + expect(ring.multiply(100000, 10000)).toBe(9999307) }) it('Should return 7 for 100000 and 10000100', () => { - expect(multiply(10000000, 20000000)).toBe(98) + expect(ring.multiply(10000000, 20000000)).toBe(98) }) }) describe('divide', () => { it('Should return 4 for 3 and 11', () => { - expect(divide(3, 11)).toBe(4) + expect(ring.divide(3, 11)).toBe(4) }) it('Should return 2 for 18 and 7', () => { - expect(divide(18, 7)).toBe(2) + expect(ring.divide(18, 7)).toBe(2) }) }) })