diff --git a/Dynamic-Programming/FastFibonacciNumber.js b/Dynamic-Programming/FastFibonacciNumber.js new file mode 100644 index 000000000..b70116782 --- /dev/null +++ b/Dynamic-Programming/FastFibonacciNumber.js @@ -0,0 +1,25 @@ +/** + * @function fastFibonacci + * @description fastFibonacci is same as fibonacci algorithm by calculating the sum of previous two fibonacci numbers but in O(log(n)). + * @param {Integer} N - The input integer + * @return {Integer} fibonacci of N. + * @see [Fast_Fibonacci_Numbers](https://www.geeksforgeeks.org/fast-doubling-method-to-find-the-nth-fibonacci-number/) + */ + +// recursive function that returns (F(n), F(n-1)) +const fib = (N) => { + if (N === 0) return [0, 1] + const [a, b] = fib(Math.trunc(N / 2)) + const c = a * (b * 2 - a) + const d = a * a + b * b + return N % 2 ? [d, c + d] : [c, d] +} + +const fastFibonacci = (N) => { + if (!Number.isInteger(N)) { + throw new TypeError('Input should be integer') + } + return fib(N)[0] +} + +export { fastFibonacci } diff --git a/Dynamic-Programming/tests/FastFibonacciNumber.test.js b/Dynamic-Programming/tests/FastFibonacciNumber.test.js new file mode 100644 index 000000000..af45a3c92 --- /dev/null +++ b/Dynamic-Programming/tests/FastFibonacciNumber.test.js @@ -0,0 +1,23 @@ +import { fastFibonacci } from '../FastFibonacciNumber' + +describe('Testing FibonacciNumber', () => { + const errorCases = ['0', '12', true] + + test.each(errorCases)('throws an error if %p is invalid', (input) => { + expect(() => { + fastFibonacci(input) + }).toThrow() + }) + + const testCases = [ + [0, 0], + [1, 1], + [10, 55], + [25, 75025], + [40, 102334155] + ] + + test.each(testCases)('if input is %i it returns %i', (input, expected) => { + expect(fastFibonacci(input)).toBe(expected) + }) +})