Fibonacci.js

/**
 * @class Fibonacci
 * @classdesc
 * A algorithm to work fibonacci.
 * 
 * Example: {@link https://codesandbox.io/s/201flaviosilva-utils-fibonacci-cnbxyv}
 * @see {@link https://pt.wikipedia.org/wiki/Sequ%C3%AAncia_de_Fibonacci}
 * 
 * @example new Fibonacci();
 * @example
 *	import { Fibonacci } from "201flaviosilva-utils";
 *	const f = new Fibonacci();
 *	for (i = 0; i < 10; i++) console.log(f.next()); // 1,2,3,5,8,13,21,34,55,89
 *	for (i = 0; i < 5; i++) console.log(f.before()); // 55,34,21,13,8
 * 
 * @constructor
 */
export class Fibonacci {
	constructor() {
		/**
		 * Used as helper value to calculate the next number.
		 * 
		 * Used to save the last valeu
		 * 
		 * @type {number}
		 * @private
		 */
		this._lastNumber = 0;

		/**
		 * Used as helper value to calculate the next number.
		 * 
		 * Used to save the next valeu
		 * 
		 * @type {number[]}
		 * @private
		 */
		this._currentNumber = 1;

		/**
		 * Contains the current state of the sequence
		 * 
		 * @type {number[]}
		 */
		this.sequence = [0];
	}

	/**
	 * Return the next number in the fibonacci sequence
	 * 
	 * @example new Fibonacci().next(); // 1
	 * 
	 * @returns {number}
	 * @memberof Fibonacci
	 */
	next() {
		const x = this._currentNumber + this._lastNumber;
		this._lastNumber = this._currentNumber;
		this._currentNumber = x;

		this.sequence.push(x);

		return this._currentNumber;
	}

	/**
	 * Return last number in sequence
	 * 
	 * @example new Fibonacci().current(); // 3
	 * 
	 * @returns {number}
	 * @memberof Fibonacci
	 */
	current() {
		return this.sequence[this.sequence.length - 1];
	}

	/**
	 * Return the next number in the fibonacci sequence
	 * 
	 * @example
	 * const f = new Fibonacci()
	 * f.next(); // 1
	 * f.next(); // 2
	 * f.before() // 1
	 * 
	 * @returns {number}
	 * @memberof Fibonacci
	 */
	before() {
		if (this.sequence.length > 1) {
			this._lastNumber = this._currentNumber - this._lastNumber;
			this._currentNumber = this._currentNumber - this._lastNumber;

			this.sequence.pop();

			return this._currentNumber;
		}
	}
}

/**
 * Runs the fibonacci sequence for the given times
 * 
 * @see {@link https://pt.wikipedia.org/wiki/Sequ%C3%AAncia_de_Fibonacci}
 * 
 * @example fibonacci(2); // [0,1]
 * @example fibonacci(5); // [0,1,1,2,3]
 * @example fibonacci(10); // [0,1,1,2,3,5,8,13,21,34]
 * 
 * @param {number} times - number of times to run
 * @returns {number[]}
 */
export function fibonacciSequence(times = 20) {
	const sequence = [0, 1];
	while (sequence.length < times) {
		sequence.push(sequence[sequence.length - 2] + sequence[sequence.length - 1]);
	}
	return sequence;
}

/**
 * Runs the fibonacci sequence until the maximum given number
 * 
 * @example fibonacciUntil(2); // [0,1,1]
 * @example fibonacciUntil(5); // [0,1,1,2,3]
 * @example fibonacciUntil(100); // [0,1,1,2,3,5,8,13,21,34,55,89]
 * 
 * @param {number} max - max number to get
 * @returns {number[]}
 */
export function fibonacciUntil(max = 100) {
	const sequence = [0, 1];
	do {
		const calc = sequence[sequence.length - 2] + sequence[sequence.length - 1];
		if (calc >= max) return sequence;
		sequence.push(sequence[sequence.length - 2] + sequence[sequence.length - 1]);
	} while (sequence[sequence.length - 1] < max);
}

/**
 * Create a fibonacci sequence starts and end with a given values
 * 
 * @example fibonacciCustomSequence(5, 20); // [5,10,15,25]
 * @example fibonacciCustomSequence(10, 120); // [10,20,30,50,80,130]
 * @example fibonacciCustomSequence(50); // [50,100,150]
 * 
 * @param {number} start - number to start the sequence
 * @param {number} end - max number to stop
 * @returns {number[]}
 */
export function fibonacciCustomSequence(start = 1, end = 100) {
	const sequence = [];
	let lastNumber = 0;
	let currentNumber = start;

	while (currentNumber <= end) {
		const next = currentNumber + lastNumber;
		lastNumber = currentNumber;
		currentNumber = next;
		sequence.push(currentNumber);
	}

	return sequence;
}

/**
 * A other way to solve the fibonacci sequence, with recursion.
 * 
 * @example recursiveFibonacci(5); // 5
 * @example recursiveFibonacci(8); // 21
 * @example recursiveFibonacci(10); // 55
 * 
 * @param {number} terms - number of terms
 * @returns {number}
 */
export function recursiveFibonacci(terms = 10) {
	if (terms <= 1) return terms;
	return recursiveFibonacci(terms - 1) + recursiveFibonacci(terms - 2);
}