Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 1x 1x 1x 1x 1x 1x 12x 1x 1x 12x 12x 12x 1x 1x 1x 1x 1x 1x 1x 1x 14x 2x 2x 14x 14x 2x 2x 2x 14x 14x 3x 7x 14x 1x 1x 7x 7x 7x 59x 59x 59x 7x 7x 1x 1x 61x 61x 61x 61x 61x 61x 1x 1x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 1x 1x 22041x 11022x 11022x 22041x 22041x 11019x 11019x 11019x 11019x 11019x 11019x 11019x 11019x 11019x 22041x 1x | /**
* The Fibonacci class.
* It can be used to calculate the Fibonacci number for a given index using either an iterative or a recursive approach.
*/
export class Fibonacci {
private readonly fibonacciNumbers: bigint[];
private readonly method: 'iterative' | 'recursive';
constructor(method: 'iterative' | 'recursive' = 'iterative') {
this.fibonacciNumbers = [0n, 1n];
this.method = method;
}
/**
* Gets the Fibonacci number for the given index.
*
* @param fibonacciIndex - The index of the Fibonacci number to retrieve.
* @returns A Promise that resolves with the Fibonacci number for the given index.
*/
public async getValueFor(fibonacciIndex: number): Promise<bigint> {
if (!Number.isInteger(fibonacciIndex) || fibonacciIndex < 0) {
throw new Error(`Invalid input fibonacci index: ${fibonacciIndex}`);
}
if (fibonacciIndex < this.fibonacciNumbers.length) {
const alreadyCalculated = this.fibonacciNumbers.at(fibonacciIndex) as bigint;
return Promise.resolve(alreadyCalculated);
}
return this.method === 'recursive'
? this.calculateRecursively(BigInt(fibonacciIndex))
: this.calculateIteratively(fibonacciIndex);
}
private async calculateIteratively(inputNumber: number): Promise<bigint> {
let [previous, current] = [0n, 1n];
let i = 2;
while (i <= inputNumber) {
[previous, current] = await this.calculateNext(previous, current);
i++;
}
return current;
}
private async calculateNext(previous: bigint, current: bigint): Promise<[bigint, bigint]> {
return new Promise((resolve) => {
setImmediate(() => {
return resolve([current, previous + current]);
});
});
}
public async getValueForWithLastOptions(
fibonacciIndex: number,
lastOptions: { lastIndex: number; lastValues: bigint[] },
) {
if (!Number.isInteger(fibonacciIndex) || fibonacciIndex < 0) {
throw new Error(`Invalid input fibonacci index: ${fibonacciIndex}`);
}
if (fibonacciIndex <= lastOptions.lastIndex) {
throw new Error(`Fibonacci index is less than or equal to last index`);
}
let [previous, current] = lastOptions.lastValues;
let i = lastOptions.lastIndex;
while (i < fibonacciIndex) {
[previous, current] = await this.calculateNext(previous, current);
i++;
}
return current;
}
private calculateRecursively(fibonacciIndex: bigint): Promise<bigint> {
if (fibonacciIndex < 2n) {
return Promise.resolve(fibonacciIndex);
}
return new Promise((resolve, reject) => {
setImmediate(() => {
void (async () => {
const left = await this.calculateRecursively(fibonacciIndex - 1n);
const right = await this.calculateRecursively(fibonacciIndex - 2n);
const result = left + right;
resolve(result);
})().catch(reject);
});
});
}
}
|