diff --git a/Maths/PrimesInRange.js b/Maths/PrimesInRange.js new file mode 100644 index 0000000000..f106510a20 --- /dev/null +++ b/Maths/PrimesInRange.js @@ -0,0 +1,38 @@ +/** + * @function primesInRange + * @description Returns all prime numbers in a given range [start, end] + * using the Sieve of Eratosthenes algorithm. + * @param {number} start - The start of the range (inclusive) + * @param {number} end - The end of the range (inclusive) + * @returns {number[]} - Array of all prime numbers in the range + * @see https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + * @example primesInRange(1, 10) => [2, 3, 5, 7] + * @example primesInRange(10, 20) => [11, 13, 17, 19] + */ +const primesInRange = (start, end) => { + if (!Number.isInteger(start) || !Number.isInteger(end)) { + throw new TypeError('Both inputs must be integers') + } + if (start < 1 || end < 1) { + throw new TypeError('Both inputs must be positive integers') + } + if (start > end) { + throw new RangeError('Start must be less than or equal to end') + } + const sieve = new Array(end + 1).fill(true) + sieve[0] = false + sieve[1] = false + for (let i = 2; i <= Math.sqrt(end); i++) { + if (sieve[i]) { + for (let j = i * i; j <= end; j += i) { + sieve[j] = false + } + } + } + return sieve + .slice(start) + .map((isPrime, i) => (isPrime ? start + i : null)) + .filter((n) => n !== null) +} + +export { primesInRange } diff --git a/Maths/test/PrimesInRange.test.js b/Maths/test/PrimesInRange.test.js new file mode 100644 index 0000000000..b7debf21c8 --- /dev/null +++ b/Maths/test/PrimesInRange.test.js @@ -0,0 +1,43 @@ +import { primesInRange } from '../PrimesInRange.js' + +describe('primesInRange', () => { + test('primesInRange(1, 10) returns [2,3,5,7]', () => { + expect(primesInRange(1, 10)).toEqual([2, 3, 5, 7]) + }) + + test('primesInRange(10, 20) returns [11,13,17,19]', () => { + expect(primesInRange(10, 20)).toEqual([11, 13, 17, 19]) + }) + + test('primesInRange(1, 2) returns [2]', () => { + expect(primesInRange(1, 2)).toEqual([2]) + }) + + test('primesInRange(1, 1) returns []', () => { + expect(primesInRange(1, 1)).toEqual([]) + }) + + test('primesInRange(14, 16) returns []', () => { + expect(primesInRange(14, 16)).toEqual([]) + }) + + test('primesInRange(1, 50) has correct count', () => { + expect(primesInRange(1, 50)).toHaveLength(15) + }) + + test('primesInRange with same start and end that is prime', () => { + expect(primesInRange(7, 7)).toEqual([7]) + }) + + test('throws TypeError for float input', () => { + expect(() => primesInRange(1.5, 10)).toThrow(TypeError) + }) + + test('throws TypeError for negative input', () => { + expect(() => primesInRange(-1, 10)).toThrow(TypeError) + }) + + test('throws RangeError when start > end', () => { + expect(() => primesInRange(10, 5)).toThrow(RangeError) + }) +})