diff --git a/Maths/SpyNumber.js b/Maths/SpyNumber.js new file mode 100644 index 0000000000..753d294df4 --- /dev/null +++ b/Maths/SpyNumber.js @@ -0,0 +1,23 @@ +/** + * @function isSpyNumber + * @description A spy number is a number where the sum of its digits + * equals the product of its digits. + * For example, 1124: 1+1+2+4=8 and 1x1x2x4=8. + * @param {number} n - A positive integer + * @returns {boolean} - True if n is a spy number, false otherwise + * @see https://en.wikipedia.org/wiki/Spy_number + * @example isSpyNumber(1124) => true + * @example isSpyNumber(123) => true + * @example isSpyNumber(1234) => false + */ +const isSpyNumber = (n) => { + if (!Number.isInteger(n) || n < 1) { + throw new TypeError('Input must be a positive integer') + } + const digits = String(n).split('').map(Number) + const sum = digits.reduce((acc, d) => acc + d, 0) + const product = digits.reduce((acc, d) => acc * d, 1) + return sum === product +} + +export { isSpyNumber } diff --git a/Maths/test/SpyNumber.test.js b/Maths/test/SpyNumber.test.js new file mode 100644 index 0000000000..ad38904023 --- /dev/null +++ b/Maths/test/SpyNumber.test.js @@ -0,0 +1,47 @@ +import { isSpyNumber } from '../SpyNumber.js' + +describe('isSpyNumber', () => { + test('1 is a spy number (1=1)', () => { + expect(isSpyNumber(1)).toBe(true) + }) + + test('123 is a spy number (1+2+3=6, 1x2x3=6)', () => { + expect(isSpyNumber(123)).toBe(true) + }) + + test('1124 is a spy number (1+1+2+4=8, 1x1x2x4=8)', () => { + expect(isSpyNumber(1124)).toBe(true) + }) + + test('132 is a spy number (1+3+2=6, 1x3x2=6)', () => { + expect(isSpyNumber(132)).toBe(true) + }) + + test('1234 is NOT a spy number (1+2+3+4=10, 1x2x3x4=24)', () => { + expect(isSpyNumber(1234)).toBe(false) + }) + + test('22 is NOT a spy number (2+2=4, 2x2=4) wait it is!', () => { + expect(isSpyNumber(22)).toBe(true) + }) + + test('12 is NOT a spy number (1+2=3, 1x2=2)', () => { + expect(isSpyNumber(12)).toBe(false) + }) + + test('11 is a spy number (1+1=2, 1x1=1) is false', () => { + expect(isSpyNumber(11)).toBe(false) + }) + + test('throws TypeError for zero', () => { + expect(() => isSpyNumber(0)).toThrow(TypeError) + }) + + test('throws TypeError for negative input', () => { + expect(() => isSpyNumber(-123)).toThrow(TypeError) + }) + + test('throws TypeError for float input', () => { + expect(() => isSpyNumber(1.5)).toThrow(TypeError) + }) +})