Last active
August 9, 2018 08:58
-
-
Save tinkertrain/1042562020338d53bb404686e5385ba7 to your computer and use it in GitHub Desktop.
Even Fibonacci Numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Class to produce Fibonacci series and actions on them */ | |
class Fibonacci { | |
/** | |
* Initialize the arrays to store the Fibonacci series | |
* complete: All the values that have been calculated across uses | |
* current: The current list of values | |
*/ | |
constructor() { | |
this.series = { | |
complete: [], | |
current: [], | |
}; | |
} | |
/** | |
* Calculate the series of Fibonacci Numbers up to a certain given limit | |
* | |
* @param {numer} limit The maximum value ont the Fibonacci series to calculate | |
* @return {array} The calculated Fibonacci series | |
*/ | |
getFiboSeries(limit = 4000000) { | |
let a; | |
let b; | |
let c; | |
// If the series is empty, start from the beginning | |
if (!this.series.complete.length) { | |
this.series.complete.push(1); | |
a = 0; | |
b = 1; | |
} else { | |
// If the series is not empty, instead of calculating from the beginning | |
// use the already calculated series | |
let seriesLength = this.series.complete.length; | |
a = this.series.complete[seriesLength - 2]; | |
b = this.series.complete[seriesLength - 1]; | |
} | |
c = a + b; | |
// Don't calculate the series if the limit is lower than what we already have calculated before | |
if (limit > b) { | |
while (c < limit) { | |
a = b; | |
b = c; | |
c = a + b; | |
// Don't include `c` if it's bigger than the limit | |
if (c <= limit) { | |
this.series.complete.push(c); | |
} | |
} | |
this.series.current = [...this.series.complete]; | |
return this.series.current; | |
} | |
// If we have calcaulated the series already, find the position of the closest element of the limit | |
// and return the series up until that point | |
let idx = this._findClosestIndex(limit, this.series.complete); | |
let val = this.series.complete[idx]; | |
// Don't include the element at idx if it's bigger than the limit | |
this.series.current = val <= limit ? this.series.complete.slice(0, idx + 1) : this.series.complete.slice(0, idx); | |
return this.series.current; | |
} | |
/** | |
* Calculate the sum of the current Fibonacci series, with options: all, even or odd numbers. | |
* If no parameter is passed, all is the default | |
* @param {object} {} Config object: all, even, odd | |
* @return {number} The sum | |
*/ | |
calculateSum({ even = false, odd = false, all = false} = {}) { | |
// Allow the use of the function when passing no config object, default to `all` | |
if (!even && !odd && !all) { | |
all = true; | |
} | |
return this.series.current.reduce(function calculateSum(previousValue, currentValue) { | |
if (all || (even && odd)) { | |
return currentValue + previousValue; | |
} else { | |
if (even && currentValue % 2 === 0) { | |
return currentValue + previousValue; | |
} else if (odd && currentValue % 2 !== 0) { | |
return currentValue + previousValue; | |
} else { | |
return previousValue; | |
} | |
} | |
}, 0); | |
} | |
/** | |
* Using binary search, find the closest value to the given `goal` and return its position in the array | |
* @param {number} goal The value to find | |
* @param {array} array The array to look in | |
* @return {number} The index of the element | |
*/ | |
_findClosestIndex (goal, array) { | |
let mid; | |
let low = 0; | |
let high = array.length - 1; | |
while (high - low > 1) { | |
mid = Math.floor((low + high) / 2); | |
if (array[mid] < goal) { | |
low = mid; | |
} else { | |
high = mid; | |
} | |
} | |
if (goal - array[low] <= array[high] - goal) { | |
return low; | |
} | |
return high; | |
} | |
} | |
let fibo = new Fibonacci(); | |
console.log(fibo.getFiboSeries(24)); // [ 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377 ] | |
console.log(fibo.getFiboSeries(13)); // [ 1, 2, 3, 5, 8, 13 ] | |
console.log(fibo.calculateSum()); // 32 | |
console.log(fibo.calculateSum({odd: true})); // 22 | |
console.log(fibo.calculateSum({even: true})); // 10 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment