diff --git a/Maths/PerrinNumber.js b/Maths/PerrinNumber.js new file mode 100644 index 0000000000..e1dd960812 --- /dev/null +++ b/Maths/PerrinNumber.js @@ -0,0 +1,30 @@ +/** + * @function perrinNumber + * @description The Perrin sequence is similar to Padovan but starts + * with 3, 0, 2. Each number is the sum of the second and third + * preceding numbers. + * Sequence: 3, 0, 2, 3, 2, 5, 5, 7, 10, 12, 17... + * @param {number} n - The position in the Perrin sequence (0-indexed) + * @returns {number} - The nth Perrin number + * @see https://en.wikipedia.org/wiki/Perrin_number + * @example perrinNumber(0) => 3 + * @example perrinNumber(4) => 2 + * @example perrinNumber(6) => 5 + */ +const perrinNumber = (n) => { + if (!Number.isInteger(n) || n < 0) { + throw new TypeError('Input must be a non-negative integer') + } + if (n === 0) return 3 + if (n === 1) return 0 + if (n === 2) return 2 + let a = 3 + let b = 0 + let c = 2 + for (let i = 3; i <= n; i++) { + ;[a, b, c] = [b, c, a + b] + } + return c +} + +export { perrinNumber } diff --git a/Maths/test/PerrinNumber.test.js b/Maths/test/PerrinNumber.test.js new file mode 100644 index 0000000000..e362696482 --- /dev/null +++ b/Maths/test/PerrinNumber.test.js @@ -0,0 +1,51 @@ +import { perrinNumber } from '../PerrinNumber.js' + +describe('perrinNumber', () => { + test('perrinNumber(0) returns 3', () => { + expect(perrinNumber(0)).toBe(3) + }) + + test('perrinNumber(1) returns 0', () => { + expect(perrinNumber(1)).toBe(0) + }) + + test('perrinNumber(2) returns 2', () => { + expect(perrinNumber(2)).toBe(2) + }) + + test('perrinNumber(3) returns 3', () => { + expect(perrinNumber(3)).toBe(3) + }) + + test('perrinNumber(4) returns 2', () => { + expect(perrinNumber(4)).toBe(2) + }) + + test('perrinNumber(5) returns 5', () => { + expect(perrinNumber(5)).toBe(5) + }) + + test('perrinNumber(6) returns 5', () => { + expect(perrinNumber(6)).toBe(5) + }) + + test('perrinNumber(7) returns 7', () => { + expect(perrinNumber(7)).toBe(7) + }) + + test('perrinNumber(8) returns 10', () => { + expect(perrinNumber(8)).toBe(10) + }) + + test('perrinNumber(9) returns 12', () => { + expect(perrinNumber(9)).toBe(12) + }) + + test('throws TypeError for negative input', () => { + expect(() => perrinNumber(-1)).toThrow(TypeError) + }) + + test('throws TypeError for float input', () => { + expect(() => perrinNumber(1.5)).toThrow(TypeError) + }) +})