diff --git a/Maths/LucasNumber.js b/Maths/LucasNumber.js new file mode 100644 index 0000000000..0ffbfd913d --- /dev/null +++ b/Maths/LucasNumber.js @@ -0,0 +1,26 @@ +/** + * @function lucasNumber + * @description Lucas numbers are an integer sequence similar to Fibonacci, + * starting with 2 and 1. Each subsequent number is the sum of the two + * preceding ones: 2, 1, 3, 4, 7, 11, 18, 29, ... + * @param {number} n - The position in the Lucas sequence (0-indexed) + * @returns {number} - The nth Lucas number + * @see https://en.wikipedia.org/wiki/Lucas_number + * @example lucasNumber(0) => 2 + * @example lucasNumber(4) => 7 + */ +const lucasNumber = (n) => { + if (!Number.isInteger(n) || n < 0) { + throw new TypeError('Input must be a non-negative integer') + } + if (n === 0) return 2 + if (n === 1) return 1 + let a = 2 + let b = 1 + for (let i = 2; i <= n; i++) { + ;[a, b] = [b, a + b] + } + return b +} + +export { lucasNumber } diff --git a/Maths/test/LucasNumber.test.js b/Maths/test/LucasNumber.test.js new file mode 100644 index 0000000000..cd11074d3a --- /dev/null +++ b/Maths/test/LucasNumber.test.js @@ -0,0 +1,35 @@ +import { lucasNumber } from '../LucasNumber.js' + +describe('lucasNumber', () => { + test('lucasNumber(0) returns 2', () => { + expect(lucasNumber(0)).toBe(2) + }) + + test('lucasNumber(1) returns 1', () => { + expect(lucasNumber(1)).toBe(1) + }) + + test('lucasNumber(2) returns 3', () => { + expect(lucasNumber(2)).toBe(3) + }) + + test('lucasNumber(4) returns 7', () => { + expect(lucasNumber(4)).toBe(7) + }) + + test('lucasNumber(6) returns 18', () => { + expect(lucasNumber(6)).toBe(18) + }) + + test('lucasNumber(10) returns 123', () => { + expect(lucasNumber(10)).toBe(123) + }) + + test('throws TypeError for negative input', () => { + expect(() => lucasNumber(-1)).toThrow(TypeError) + }) + + test('throws TypeError for float input', () => { + expect(() => lucasNumber(1.5)).toThrow(TypeError) + }) +})