From 1d88e87116626e08a066b8434575d93b054150d4 Mon Sep 17 00:00:00 2001 From: sarthakgupta1907-cell Date: Mon, 9 Nov 2026 12:38:07 +0530 Subject: [PATCH 1/2] feat: add interquartile range algorithm --- Maths/InterquartileRange.js | 31 ++++++++++++++++++++ Maths/test/InterquartileRange.test.js | 41 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 Maths/InterquartileRange.js create mode 100644 Maths/test/InterquartileRange.test.js diff --git a/Maths/InterquartileRange.js b/Maths/InterquartileRange.js new file mode 100644 index 0000000000..691460487f --- /dev/null +++ b/Maths/InterquartileRange.js @@ -0,0 +1,31 @@ +/** + * @function interquartileRange + * @description Calculates the interquartile range (IQR) of an array. + * IQR is the difference between the 75th and 25th percentiles, + * representing the middle 50% spread of the data. + * @param {number[]} arr - An array of numbers + * @returns {number} - The interquartile range + * @see https://en.wikipedia.org/wiki/Interquartile_range + * @example interquartileRange([1, 2, 3, 4, 5]) => 2 + * @example interquartileRange([1, 2, 3, 4, 5, 6, 7]) => 3 + */ +const interquartileRange = (arr) => { + if (!Array.isArray(arr) || arr.length === 0) { + throw new TypeError('Input must be a non-empty array') + } + if (!arr.every((n) => typeof n === 'number' && !isNaN(n))) { + throw new TypeError('All elements must be numbers') + } + const sorted = [...arr].sort((a, b) => a - b) + const getPercentile = (data, p) => { + if (p === 0) return data[0] + if (p === 100) return data[data.length - 1] + const index = (p / 100) * (data.length - 1) + const lower = Math.floor(index) + const upper = Math.ceil(index) + return data[lower] + (data[upper] - data[lower]) * (index - lower) + } + return getPercentile(sorted, 75) - getPercentile(sorted, 25) +} + +export { interquartileRange } diff --git a/Maths/test/InterquartileRange.test.js b/Maths/test/InterquartileRange.test.js new file mode 100644 index 0000000000..e851cb8654 --- /dev/null +++ b/Maths/test/InterquartileRange.test.js @@ -0,0 +1,41 @@ +import { interquartileRange } from '../InterquartileRange.js' + +describe('interquartileRange', () => { + test('interquartileRange([1,2,3,4,5]) returns 2', () => { + expect(interquartileRange([1, 2, 3, 4, 5])).toBeCloseTo(2) + }) + + test('interquartileRange([1,2,3,4,5,6,7]) returns 3', () => { + expect(interquartileRange([1, 2, 3, 4, 5, 6, 7])).toBeCloseTo(3) + }) + + test('interquartileRange identical elements returns 0', () => { + expect(interquartileRange([5, 5, 5, 5])).toBe(0) + }) + + test('interquartileRange works with unsorted array', () => { + expect(interquartileRange([5, 3, 1, 4, 2])).toBeCloseTo(2) + }) + + test('interquartileRange works with negative numbers', () => { + expect(interquartileRange([-3, -2, -1, 0, 1, 2, 3])).toBeCloseTo(3) + }) + + test('interquartileRange does not mutate original array', () => { + const arr = [5, 3, 1, 4, 2] + interquartileRange(arr) + expect(arr).toEqual([5, 3, 1, 4, 2]) + }) + + test('throws TypeError for empty array', () => { + expect(() => interquartileRange([])).toThrow(TypeError) + }) + + test('throws TypeError for non-array input', () => { + expect(() => interquartileRange('123')).toThrow(TypeError) + }) + + test('throws TypeError for array with non-numbers', () => { + expect(() => interquartileRange([1, 'two', 3])).toThrow(TypeError) + }) +}) From 6adce4c75546d0f711bddfd9329ed7cb40825a8e Mon Sep 17 00:00:00 2001 From: sarthakgupta1907-cell Date: Mon, 9 Nov 2026 12:50:41 +0530 Subject: [PATCH 2/2] feat: add Smith number algorithm --- Maths/SmithNumber.js | 41 +++++++++++++++++++++++++++++ Maths/test/SmithNumber.test.js | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 Maths/SmithNumber.js create mode 100644 Maths/test/SmithNumber.test.js diff --git a/Maths/SmithNumber.js b/Maths/SmithNumber.js new file mode 100644 index 0000000000..16bacce27f --- /dev/null +++ b/Maths/SmithNumber.js @@ -0,0 +1,41 @@ +/** + * @function isSmithNumber + * @description A Smith number is a composite number where the sum of + * its digits equals the sum of the digits of its prime factors. + * For example, 4: prime factors are 2,2 → 2+2=4, digit sum=4. + * @param {number} n - A positive integer greater than 1 + * @returns {boolean} - True if n is a Smith number, false otherwise + * @see https://en.wikipedia.org/wiki/Smith_number + * @example isSmithNumber(4) => true + * @example isSmithNumber(22) => true + * @example isSmithNumber(13) => false + */ +const isSmithNumber = (n) => { + if (!Number.isInteger(n) || n < 2) { + throw new TypeError('Input must be an integer greater than or equal to 2') + } + const digitSum = (num) => + String(num) + .split('') + .reduce((sum, d) => sum + Number(d), 0) + const primeFactors = (num) => { + const factors = [] + let d = 2 + let temp = num + while (d * d <= temp) { + while (temp % d === 0) { + factors.push(d) + temp = Math.floor(temp / d) + } + d++ + } + if (temp > 1) factors.push(temp) + return factors + } + const factors = primeFactors(n) + if (factors.length === 1 && factors[0] === n) return false + const primeDigitSum = factors.reduce((sum, f) => sum + digitSum(f), 0) + return digitSum(n) === primeDigitSum +} + +export { isSmithNumber } diff --git a/Maths/test/SmithNumber.test.js b/Maths/test/SmithNumber.test.js new file mode 100644 index 0000000000..4bdeff4ac3 --- /dev/null +++ b/Maths/test/SmithNumber.test.js @@ -0,0 +1,47 @@ +import { isSmithNumber } from '../SmithNumber.js' + +describe('isSmithNumber', () => { + test('4 is a Smith number (2+2=4)', () => { + expect(isSmithNumber(4)).toBe(true) + }) + + test('22 is a Smith number (2+1+1=4, 2+2=4)', () => { + expect(isSmithNumber(22)).toBe(true) + }) + + test('27 is a Smith number (2+7=9, 3+3+3=9)', () => { + expect(isSmithNumber(27)).toBe(true) + }) + + test('58 is a Smith number (5+8=13, 2+1+1=4... wait)', () => { + expect(isSmithNumber(58)).toBe(true) + }) + + test('13 is NOT a Smith number (prime)', () => { + expect(isSmithNumber(13)).toBe(false) + }) + + test('2 is NOT a Smith number (prime)', () => { + expect(isSmithNumber(2)).toBe(false) + }) + + test('7 is NOT a Smith number (prime)', () => { + expect(isSmithNumber(7)).toBe(false) + }) + + test('15 is NOT a Smith number', () => { + expect(isSmithNumber(15)).toBe(false) + }) + + test('throws TypeError for 1', () => { + expect(() => isSmithNumber(1)).toThrow(TypeError) + }) + + test('throws TypeError for negative input', () => { + expect(() => isSmithNumber(-4)).toThrow(TypeError) + }) + + test('throws TypeError for float input', () => { + expect(() => isSmithNumber(4.5)).toThrow(TypeError) + }) +})