Skip to content

Instantly share code, notes, and snippets.

@tinkertrain
Last active August 9, 2018 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tinkertrain/1042562020338d53bb404686e5385ba7 to your computer and use it in GitHub Desktop.
Save tinkertrain/1042562020338d53bb404686e5385ba7 to your computer and use it in GitHub Desktop.
Even Fibonacci Numbers
/** 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