diff --git a/Maths/UglyNumber.js b/Maths/UglyNumber.js new file mode 100644 index 0000000000..c1e6cd678c --- /dev/null +++ b/Maths/UglyNumber.js @@ -0,0 +1,26 @@ +/** + * @function isUglyNumber + * @description An ugly number is a positive integer whose prime factors + * are limited to 2, 3, and 5. + * Sequence: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12... + * @param {number} n - A positive integer + * @returns {boolean} - True if n is an ugly number, false otherwise + * @see https://en.wikipedia.org/wiki/Regular_number + * @example isUglyNumber(6) => true + * @example isUglyNumber(8) => true + * @example isUglyNumber(14) => false + */ +const isUglyNumber = (n) => { + if (!Number.isInteger(n) || n < 1) { + throw new TypeError('Input must be a positive integer') + } + let num = n + for (const factor of [2, 3, 5]) { + while (num % factor === 0) { + num = Math.floor(num / factor) + } + } + return num === 1 +} + +export { isUglyNumber } diff --git a/Maths/test/UglyNumber.test.js b/Maths/test/UglyNumber.test.js new file mode 100644 index 0000000000..d79ed63f7b --- /dev/null +++ b/Maths/test/UglyNumber.test.js @@ -0,0 +1,55 @@ +import { isUglyNumber } from '../UglyNumber.js' + +describe('isUglyNumber', () => { + test('1 is an ugly number', () => { + expect(isUglyNumber(1)).toBe(true) + }) + + test('2 is an ugly number', () => { + expect(isUglyNumber(2)).toBe(true) + }) + + test('3 is an ugly number', () => { + expect(isUglyNumber(3)).toBe(true) + }) + + test('6 is an ugly number (2 x 3)', () => { + expect(isUglyNumber(6)).toBe(true) + }) + + test('8 is an ugly number (2³)', () => { + expect(isUglyNumber(8)).toBe(true) + }) + + test('15 is an ugly number (3 x 5)', () => { + expect(isUglyNumber(15)).toBe(true) + }) + + test('30 is an ugly number (2 x 3 x 5)', () => { + expect(isUglyNumber(30)).toBe(true) + }) + + test('14 is NOT an ugly number (2 x 7)', () => { + expect(isUglyNumber(14)).toBe(false) + }) + + test('7 is NOT an ugly number (prime > 5)', () => { + expect(isUglyNumber(7)).toBe(false) + }) + + test('11 is NOT an ugly number', () => { + expect(isUglyNumber(11)).toBe(false) + }) + + test('throws TypeError for zero', () => { + expect(() => isUglyNumber(0)).toThrow(TypeError) + }) + + test('throws TypeError for negative input', () => { + expect(() => isUglyNumber(-6)).toThrow(TypeError) + }) + + test('throws TypeError for float input', () => { + expect(() => isUglyNumber(6.5)).toThrow(TypeError) + }) +})