find all possible combinations of two integers - javascript

Each time I can climb 1 or 2 steps to reach the top (3 steps for example)
1 + 1 + 1, 1 + 2, 2 + 1. There are three cases (scenarios). Here's my voodoo code (the thing is some numbers (missing) don't appear for n = 5 it's 1211. the solution would be to do the reverse string and store two versions of such strings in the hash, so duplicates will disappear and after the cycle sums them.
function setCharAt(str, index, chr) {
if (index > str.length - 1) return str;
return str.substring(0, index) + chr + str.substring(index + 1);
}
let n = 9;
find(n);
function find(n) {
let origin = n; //every loop n decreases by one when it 0 while returns false,
let sum = 1;
n -= 1; //because n once once of 1's (n = 5) 1+1+1+1+1 then 1111, 1112 etc.
if (n <= 1) return sum;
while (origin <= n * 2) { //if n = 10; only"22222" can give 10, we don't go deeper
let str = "1".repeat(n); //from "1" of n(4) to "1111"
let copyStr = str;
while (str.length === copyStr.length) { //at the end we get 2222 then 22221,
// therefore the length will change, we exit the loop
let s = str.split('').reduce((a, b) => Number(a) + Number(b), 0); //countinng elems
console.log(str, "=", s);
if (s === origin) ++sum; //if elems equals the target we increase the amount by one
let one = str.lastIndexOf("1");
let two = str.lastIndexOf("2");
if (str[one] === "1" && str[one + 1] === "2") {
str = setCharAt(str, one, "2");
str = setCharAt(str, one + 1, "1");
} else {
str = setCharAt(str, one, "2");
}
}
--n;
}
console.log(sum)
}

If i understood your question, you wanna for let say n = 5 get all combinations of 1 and 2 (when you sum it) that give a sum of 5 (11111, 1112, etc)?
It is most likely that you wanna use recursion in these kind of situations, because its much easier. If you have just two values (1 and 2) you can achieve this pretty easily:
getAllCombinations = (n = 1) => {
const combinations = [];
const recursion = (n, sum = 0, str = "") => {
if (sum > n) return;
if (sum === n) {
combinations.push(str);
return;
}
// Add 1 to sum
recursion(n, sum + 1, str + "1");
// Add 2 to sum
recursion(n, sum + 2, str + "2");
};
recursion(n);
return combinations;
};

Related

Iterate over uneven array

So I have a dataset of 16 items, I want to loop through them every 5 items after the first set of 6 so the columns are 6 5 5.
Initially I tried something like this, but then I remembered I had that one orphaned item.
if(thisI <= 6) {
y = prevtitle.position[0];
} elseif(thisI % 5 == 0) {
y = prevtitle.position[0] + w + (p *3);
} else {
y = prevtitle.position[0];
}
Not sure if there is a simple way to do the first 6 and then the next ones in five without a bunch of nested if statements.
Using Array#splice:
const splitArr = (arr = []) => {
const array = [...arr];
const res = array.length ? [array.splice(0, 6)] : [];
while(array.length) res.push(array.splice(0, 5));
return res;
}
console.log( splitArr([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]) );
Would a simple ternary expression work for you?
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
num.forEach((n,i) => {
y = (i<=6 || i % 5 == 0) ? prevtitle.position[0] : prevtitle.position[0] + w + (p *3) ;
})
I presume that you're skipping the first position, and jumps directly to the 6th position.
Just use a normal for loop.
Calculate the remainder for the number of steps that you will make. 16 % 5 results in 1 remainder.
step - countForZero + remainder sets the start point in the for loop.
i += step replaces the typical i++ in the for loop.
The method below can make any kind of leap, and it doesn't matter how many items there are in the array.
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
function getEvery(step, arr) {
let newArr = [],
remainder = arr.length % step,
countForZero = 1;
for (let i = step - countForZero + remainder; i < arr.length; i += step) {
newArr.push(arr[i]);
}
return newArr;
}
console.log( getEvery(5, num) );

find sum of multiples 3 and 5, JS

I'm given a number and I need to find the sum of the multiples of 3 and 5 below the number.
For example:
20 => 78 = 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18
My code works, but not for numbers greater than 1,000,000 (I tested it for 100,000 - it gives the result with 2sec delay). So, it should be optimized. Could someone help me? Why is my code slow? Thanks.
My logic is as follows:
add multiples to an array
filter duplicate values
sum all values
my code:
function sumOfMultiples(number) {
let numberBelow = number - 1;
let numberOfThrees = Math.floor(numberBelow / 3);
let numberOfFives = Math.floor(numberBelow / 5);
let multiples = [];
let multipleOfThree = 0;
let multipleOfFive = 0;
for (var i = 0; i < numberOfThrees; i++) {
multiples.push(multipleOfThree += 3);
}
for (var j = 0; j < numberOfFives; j++) {
multiples.push(multipleOfFive += 5);
}
return multiples
.filter((item, index) => multiples.indexOf(item) === index)
.reduce((a, b) => a + b);
}
You can also do this without using any loops.
For example if N is 1000, the sum of all multiples of 3 under 1000 is 3 + 6 + 9 ..... 999 => 3( 1 + 2 + 3 .... 333)
Similarly for 5, sum is 5(1 + 2 + 3 .... 200). But we have to subtract common multiples like 15, 30, 45 (multiples of 15)
And sum of first N natural numbers is N*(N+1)/2;
Putting all of this together
// Returns sum of first N natural numbers
const sumN = N => N*(N+1)/2;
// Returns number of multiples of a below N
const noOfMulitples = (N, a) => Math.floor((N-1)/a);
function sumOfMulitples(N) {
const n3 = noOfMulitples(N, 3); // Number of multiples of 3 under N
const n5 = noOfMulitples(N, 5); // Number of multiples of 5 under N
const n15 = noOfMulitples(N, 15); // Number of multiples of 3 & 5 under N
return 3*sumN(n3) + 5*sumN(n5) - 15*sumN(n15);
}
You can just run a loop from 1 to number, and use the modulo operator % to check if i divides 3 or 5:
function sumOfMultiples(number) {
var result = 0;
for (var i = 0; i < number; i++) {
if (i % 5 == 0 || i % 3 == 0) {
result += i;
}
}
return result;
}
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
You can do that just using a single loop.
function sumOfMultiples(number) {
let sum = 0;
for(let i = 1; i < number; i++){
if(i % 3 === 0 || i % 5 === 0){
sum += i;
}
}
return sum;
}
console.time('t');
console.log(sumOfMultiples(100000))
console.timeEnd('t')
You can do something like this
Set the difference equal to 5 - 3
Start loop with current as 0, keep looping until current is less than number,
Add 3 to current in every iteration,
Add difference to current and check if it is divisible by 5 only and less than number, than add it final result,
Add current to final result
function sumOfMultiples(number) {
let num = 0;
let difference = 5 - 3
let current = 0
while(current < number){
current += 3
let temp = current + difference
if((temp % 5 === 0) && (temp %3 !== 0) && temp < number ){
num += temp
}
difference += 2
if(current < number){
num += current
}
}
return num
}
console.log(sumOfMultiples(20))
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
you can do something like this
function multiplesOfFiveAndThree(){
let sum = 0;
for(let i = 1; i < 1000; i++) {
if (i % 3 === 0 || i % 5 === 0) sum += i;
}
return sum;
}
console.log(multiplesOfFiveAndThree());

How to find nth Fibonacci number using Javascript with O(n) complexity

Trying really hard to figure out how to solve this problem. The problem being finding nth number of Fibonacci with O(n) complexity using javascript.
I found a lot of great articles how to solve this using C++ or Python, but every time I try to implement the same logic I end up in a Maximum call stack size exceeded.
Example code in Python
MAX = 1000
# Create an array for memoization
f = [0] * MAX
# Returns n'th fuibonacci number using table f[]
def fib(n) :
# Base cases
if (n == 0) :
return 0
if (n == 1 or n == 2) :
f[n] = 1
return (f[n])
# If fib(n) is already computed
if (f[n]) :
return f[n]
if( n & 1) :
k = (n + 1) // 2
else :
k = n // 2
# Applyting above formula [Note value n&1 is 1
# if n is odd, else 0.
if((n & 1) ) :
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
else :
f[n] = (2*fib(k-1) + fib(k))*fib(k)
return f[n]
// # Driver code
// n = 9
// print(fib(n))
Then trying to port this to Javascript
const MAX = 1000;
let f = Array(MAX).fill(0);
let k;
const fib = (n) => {
if (n == 0) {
return 0;
}
if (n == 1 || n == 2) {
f[n] = 1;
return f[n]
}
if (f[n]) {
return f[n]
}
if (n & 1) {
k = Math.floor(((n + 1) / 2))
} else {
k = Math.floor(n / 2)
}
if ((n & 1)) {
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
} else {
f[n] = (2*fib(k-1) + fib(k))*fib(k)
}
return f[n]
}
console.log(fib(9))
That obviously doesn't work. In Javascript this ends up in an infinite loops. So how would you solve this using Javascript?
Thanks in advance
you can iterate from bottom to top (like tail recursion):
var fib_tail = function(n){
if(n == 0)
return 0;
if(n == 1 || n == 2)
return 1;
var prev_1 = 1, prev_2 = 1, current;
// O(n)
for(var i = 3; i <= n; i++)
{
current = prev_1 + prev_2;
prev_1 = prev_2;
prev_2 = current;
}
return current;
}
console.log(fib_tail(1000))
The problem is related to scope of the k variable. It must be inside of the function:
const fib = (n) => {
let k;
You can find far more good implementations here list
DEMO
fibonacci number in O(n) time and O(1) space complexity:
function fib(n) {
let prev = 0, next =1;
if(n < 0)
throw 'not a valid value';
if(n === prev || n === next)
return n;
while(n >= 2) {
[prev, next] = [next, prev+next];
n--;
}
return next;
}
Just use two variables and a loop that counts down the number provided.
function fib(n){
let [a, b] = [0, 1];
while (--n > 0) {
[a, b] = [b, a+b];
}
return b;
}
console.log(fib(10));
Here's a simpler way to go about it, using either iterative or recursive methods:
function FibSmartRecursive(n, a = 0, b = 1) {
return n > 1 ? FibSmartRecursive(n-1, b, a+b) : a;
}
function FibIterative(n) {
if (n < 2)
return n;
var a = 0, b = 1, c = 1;
while (--n > 1) {
a = b;
b = c;
c = a + b;
}
return c;
}
function FibMemoization(n, seenIt = {}) {//could use [] as well here
if (n < 2)
return n;
if (seenIt[n])
return seenIt[n];
return seenIt[n] = FibMemoization(n-1, seenIt) + FibMemoization(n-2, seenIt);
}
console.log(FibMemoization(25)); //75025
console.log(FibIterative(25)); //75025
console.log(FibSmartRecursive(25)); //75025
You can solve this problem without recursion using loops, runtime O(n):
function nthFibo(n) {
// Return the n-th number in the Fibonacci Sequence
const fibSeq = [0, 1]
if (n < 3) return seq[n - 1]
let i = 1
while (i < n - 1) {
seq.push(seq[i - 1] + seq[i])
i += 1
}
return seq.slice(-1)[0]
}
// Using Recursion
const fib = (n) => {
if (n <= 2) return 1;
return fib(n - 1) + fib(n - 2);
}
console.log(fib(4)) // 3
console.log(fib(10)) // 55
console.log(fib(28)) // 317811
console.log(fib(35)) // 9227465

javascript: summing even members of Fibonacci series

Yet Another (Project Euler) Fibonacci Question: Using (vanilla) javascript, I'm trying to sum the even numbers <= a given limit:
First, something is wrong with my 'if' statement, as some of the results (below) are wrong:
function fibonacciSum(limit) {
var limit = limit;
var series = [1,2];
var sum = 0;
var counter = 0;
for (var i=1; i<=33; i++) { // 33 is arbitrary, because I know this is more than enough
var prev1 = series[series.length-1];
var prev2 = series[series.length-2];
var newVal = prev1+prev2;
series.push(newVal);
counter ++;
console.log("series "+ counter + " is: " + series);
if (series[i] % 2 === 0 && series[i] <= limit) { // intending to sum only even values less than/equal to arbitrary limit
// sum = sum + series[i];
sum += series[i];
}
/*
var sum = series.reduce(function(a,b) {
/*
possible to filter here for even numbers? something like:
if (a %2 === 0)
*/
return a+b;
});
*/
console.log("SUM " + counter + ": " + sum);
} // for loop
} // fibonacci
fibonacciSum(4000000);
Results:
series 1 is: 1,2,3
SUM 1: 2
series 2 is: 1,2,3,5
SUM 2: 2
series 3 is: 1,2,3,5,8
SUM 3: 2 // looking for a '10' here
series 4 is: 1,2,3,5,8,13
SUM 4: 10
series 5 is: 1,2,3,5,8,13,21
SUM 5: 10
series 6 is: 1,2,3,5,8,13,21,34
SUM 6: 10 // looking for '44' here
Can someone please explain why neither of these working as intended?
if (series[i] % 2 === 0) { ...
... or
if (series[i] % 2 === 0 && series[i] <= limit) { ...
And secondly, as you can see I had also tried to use series.reduce(... but I can't figure how to sum only the even values; is that doable/cleaner?
Thank you,
Whiskey T.
No need for arrays. Use three variables for let's say previous, current and next numbers in fibonacci sequence.
We can also begin the sequence with 2 an 3 because there are no other even numbers that will affect the result.
We initialize the sum of even numbers with 2 because it's the current number and it's even. In a do...while we advance with the numbers in sequence and if the new numbers are even we add them to the sum. Stop when limit is reached.
function fibEvenSum(limit) {
var prev = 1,
current = 2,
next;
var sum = 2;
do {
next = prev + current;
prev = current;
current = next;
if (current >= limit)
break;
if (current % 2 == 0)
sum += current;
} while (true)
return sum;
}
This algorithm can be improved using properties of odd and even numbers:
odd + odd = even
even + even = even
even + odd = odd
This should work for you...
var fibonacciSum = function(limit) {
var nMinus2 = 1, nMinus1 = 2, evensFound = [2], sum = nMinus1;
while (sum <= limit){
var n = nMinus1 + nMinus2;
if (n % 2 == 0){
sum += n;
if (sum > limit){
break;
}
evensFound.push(n);
}
nMinus2 = nMinus1;
nMinus1 = n;
}
console.log("Evens found - " + evensFound);
return evensFound;
};
var evensFound1 = fibonacciSum(4),
evensFound2 = fibonacciSum(10),
evensFound3 = fibonacciSum(60),
evensFound4 = fibonacciSum(1000);
$(evenResults).append(evensFound1
+ "<br/>" + evensFound2
+ "<br/>" + evensFound3
+ "<br/>" + evensFound4);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="evenResults"></div>
A solution in the spirit of the one your attempted — with arrays — though as pointed out, they are not necessary.
var i = 0, sequence = [1, 2], total = 0;
while (sequence.slice(-1)[0] < 4000000) {
sequence.push(sequence.slice(-1)[0] + sequence.slice(-2)[0]);
}
for ( i; i <= sequence.length; i++ ) {
if ( sequence[i] % 2 === 0 ) {
total += sequence[i];
}
}

Generating Fibonacci Sequence

var x = 0;
var y = 1;
var z;
fib[0] = 0;
fib[1] = 1;
for (i = 2; i <= 10; i++) {
alert(x + y);
fib[i] = x + y;
x = y;
z = y;
}
I'm trying to get to generate a simple Fibonacci Sequence but there no output.
Can anybody let me know what's wrong?
You have never declared fib to be an array. Use var fib = []; to solve this.
Also, you're never modifying the y variable, neither using it.
The code below makes more sense, plus, it doesn't create unused variables:
var i;
var fib = [0, 1]; // Initialize array!
for (i = 2; i <= 10; i++) {
// Next fibonacci number = previous + one before previous
// Translated to JavaScript:
fib[i] = fib[i - 2] + fib[i - 1];
console.log(fib[i]);
}
According to the Interview Cake question, the sequence goes 0,1,1,2,3,5,8,13,21. If this is the case, this solution works and is recursive without the use of arrays.
function fibonacci(n) {
return n < 1 ? 0
: n <= 2 ? 1
: fibonacci(n - 1) + fibonacci(n - 2)
}
console.log(fibonacci(4))
Think of it like this.
fibonacci(4) .--------> 2 + 1 = 3
| / |
'--> fibonacci(3) + fibonacci(2)
| ^
| '----------- 2 = 1 + 1 <----------.
1st step -> | ^ |
| | |
'----> fibonacci(2) -' + fibonacci(1)-'
Take note, this solution is not very efficient though.
Yet another answer would be to use es6 generator functions.
function* fib() {
var current = a = b = 1;
yield 1;
while (true) {
current = b;
yield current;
b = a + b;
a = current;
}
}
sequence = fib();
sequence.next(); // 1
sequence.next(); // 1
sequence.next(); // 2
// ...
Here's a simple function to iterate the Fibonacci sequence into an array using arguments in the for function more than the body of the loop:
fib = function(numMax){
for(var fibArray = [0,1], i=0,j=1,k=0; k<numMax;i=j,j=x,k++ ){
x=i+j;
fibArray.push(x);
}
console.log(fibArray);
}
fib(10)
[ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ]
You should've declared the fib variable to be an array in the first place (such as var fib = [] or var fib = new Array()) and I think you're a bit confused about the algorithm.
If you use an array to store the fibonacci sequence, you do not need the other auxiliar variables (x,y,z) :
var fib = [0, 1];
for(var i=fib.length; i<10; i++) {
fib[i] = fib[i-2] + fib[i-1];
}
console.log(fib);
Click for the demo
You should consider the recursive method too (note that this is an optimised version) :
function fib(n, undefined){
if(fib.cache[n] === undefined){
fib.cache[n] = fib(n-1) + fib(n-2);
}
return fib.cache[n];
}
fib.cache = [0, 1, 1];
and then, after you call the fibonacci function, you have all the sequence in the fib.cache field :
fib(1000);
console.log(fib.cache);
The golden ration "phi" ^ n / sqrt(5) is asymptotic to the fibonacci of n, if we round that value up, we indeed get the fibonacci value.
function fib(n) {
let phi = (1 + Math.sqrt(5))/2;
let asymp = Math.pow(phi, n) / Math.sqrt(5);
return Math.round(asymp);
}
fib(1000); // 4.346655768693734e+208 in just a few milliseconds
This runs faster on large numbers compared to the recursion based solutions.
You're not assigning a value to z, so what do you expect y=z; to do? Likewise you're never actually reading from the array. It looks like you're trying a combination of two different approaches here... try getting rid of the array entirely, and just use:
// Initialization of x and y as before
for (i = 2; i <= 10; i++)
{
alert(x + y);
z = x + y;
x = y;
y = z;
}
EDIT: The OP changed the code after I'd added this answer. Originally the last line of the loop was y = z; - and that makes sense if you've initialized z as per my code.
If the array is required later, then obviously that needs to be populated still - but otherwise, the code I've given should be fine.
Another easy way to achieve this:
function fibonacciGenerator(n) {
// declare the array starting with the first 2 values of the fibonacci sequence
// starting at array index 1, and push current index + previous index to the array
for (var fibonacci = [0, 1], i = 2; i < n; i++)
fibonacci.push(fibonacci[i-1] + fibonacci[i - 2])
return fibonacci
}
console.log( fibonacciGenerator(10) )
function fib(n) {
if (n <= 1) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
fib(10); // returns 55
fibonacci 1,000 ... 10,000 ... 100,000
Some answers run into issues when trying to calculate large fibonacci numbers. Others are approximating numbers using phi. This answer will show you how to calculate a precise series of large fibonacci numbers without running into limitations set by JavaScript's floating point implementation.
Below, we generate the first 1,000 fibonacci numbers in a few milliseconds. Later, we'll do 100,000!
const { fromInt, toString, add } =
Bignum
const bigfib = function* (n = 0)
{
let a = fromInt (0)
let b = fromInt (1)
let _
while (n >= 0) {
yield toString (a)
_ = a
a = b
b = add (b, _)
n = n - 1
}
}
console.time ('bigfib')
const seq = Array.from (bigfib (1000))
console.timeEnd ('bigfib')
// 25 ms
console.log (seq.length)
// 1001
console.log (seq)
// [ 0, 1, 1, 2, 3, ... 995 more elements ]
Let's see the 1,000th fibonacci number
console.log (seq [1000])
// 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
10,000
This solution scales quite nicely. We can calculate the first 10,000 fibonacci numbers in under 2 seconds. At this point in the sequence, the numbers are over 2,000 digits long – way beyond the capacity of JavaScript's floating point numbers. Still, our result includes precise values without making approximations.
console.time ('bigfib')
const seq = Array.from (bigfib (10000))
console.timeEnd ('bigfib')
// 1877 ms
console.log (seq.length)
// 10001
console.log (seq [10000] .length)
// 2090
console.log (seq [10000])
// 3364476487 ... 2070 more digits ... 9947366875
Of course all of that magic takes place in Bignum, which we will share now. To get an intuition for how we will design Bignum, recall how you added big numbers using pen and paper as a child...
1259601512351095520986368
+ 50695640938240596831104
---------------------------
?
You add each column, right to left, and when a column overflows into the double digits, remembering to carry the 1 over to the next column...
... <-001
1259601512351095520986368
+ 50695640938240596831104
---------------------------
... <-472
Above, we can see that if we had two 10-digit numbers, it would take approximately 30 simple additions (3 per column) to compute the answer. This is how we will design Bignum to work
const Bignum =
{ fromInt: (n = 0) =>
n < 10
? [ n ]
: [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
, fromString: (s = "0") =>
Array.from (s, Number) .reverse ()
, toString: (b) =>
Array.from (b) .reverse () .join ('')
, add: (b1, b2) =>
{
const len = Math.max (b1.length, b2.length)
let answer = []
let carry = 0
for (let i = 0; i < len; i = i + 1) {
const x = b1[i] || 0
const y = b2[i] || 0
const sum = x + y + carry
answer.push (sum % 10)
carry = sum / 10 >> 0
}
if (carry > 0) answer.push (carry)
return answer
}
}
We'll run a quick test to verify our example above
const x =
fromString ('1259601512351095520986368')
const y =
fromString ('50695640938240596831104')
console.log (toString (add (x,y)))
// 1310297153289336117817472
And now a complete program demonstration. Expand it to calculate the precise 10,000th fibonacci number in your own browser! Note, the result is the same as the answer provided by wolfram alpha
const Bignum =
{ fromInt: (n = 0) =>
n < 10
? [ n ]
: [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
, fromString: (s = "0") =>
Array.from (s, Number) .reverse ()
, toString: (b) =>
Array.from (b) .reverse () .join ('')
, add: (b1, b2) =>
{
const len = Math.max (b1.length, b2.length)
let answer = []
let carry = 0
for (let i = 0; i < len; i = i + 1) {
const x = b1[i] || 0
const y = b2[i] || 0
const sum = x + y + carry
answer.push (sum % 10)
carry = sum / 10 >> 0
}
if (carry > 0) answer.push (carry)
return answer
}
}
const { fromInt, toString, add } =
Bignum
const bigfib = function* (n = 0)
{
let a = fromInt (0)
let b = fromInt (1)
let _
while (n >= 0) {
yield toString (a)
_ = a
a = b
b = add (b, _)
n = n - 1
}
}
console.time ('bigfib')
const seq = Array.from (bigfib (10000))
console.timeEnd ('bigfib')
// 1877 ms
console.log (seq.length)
// 10001
console.log (seq [10000] .length)
// 2090
console.log (seq [10000])
// 3364476487 ... 2070 more digits ... 9947366875
100,000
I was just curious how far this little script could go. It seems like the only limitation is just time and memory. Below, we calculate the first 100,000 fibonacci numbers without approximation. Numbers at this point in the sequence are over 20,000 digits long, wow! It takes 3.18 minutes to complete but the result still matches the answer from wolfram alpha
console.time ('bigfib')
const seq = Array.from (bigfib (100000))
console.timeEnd ('bigfib')
// 191078 ms
console.log (seq .length)
// 100001
console.log (seq [100000] .length)
// 20899
console.log (seq [100000])
// 2597406934 ... 20879 more digits ... 3428746875
BigInt
JavaScript now has native support for BigInt. This allows for calculating huge integers very quickly -
function* fib (n)
{ let a = 0n
let b = 1n
let _
while (n >= 0) {
yield a.toString()
_ = a
a = b
b = b + _
n = n - 1
}
}
console.time("fib(1000)")
const result = Array.from(fib(1000))
console.timeEnd("fib(1000)")
document.body.textContent = JSON.stringify(result, null, 2)
body {
font-family: monospace;
white-space: pre;
}
I like the fact that there are so many ways to create a fibonacci sequence in JS. I will try to reproduce a few of them. The goal is to output a sequence to console (like {n: 6, fiboNum: 8})
Good ol' closure
// The IIFE form is purposefully omitted. See below.
const fiboGenClosure = () => {
let [a, b] = [0, 1];
let n = 0;
return (fiboNum = a) => {
[a, b] = [b, a + b];
return {
n: n++,
fiboNum: fiboNum
};
};
}
// Gets the sequence until given nth number. Always returns a new copy of the main function, so it is possible to generate multiple independent sequences.
const generateFiboClosure = n => {
const newSequence = fiboGenClosure();
for (let i = 0; i <= n; i++) {
console.log(newSequence());
}
}
generateFiboClosure(21);
Fancy ES6 generator
Similar to the closure pattern above, using the advantages of generator function and for..of loop.
// The 'n' argument is a substitute for index.
function* fiboGen(n = 0) {
let [a, b] = [0, 1];
while (true) {
yield [a, n++];
[a, b] = [b, a + b];
}
}
// Also gives a new sequence every time is invoked.
const generateFibonacci = n => {
const iterator = fiboGen();
for (let [value, index] of iterator) {
console.log({
n: index,
fiboNum: value
});
if (index >= n) break;
}
}
generateFibonacci(21);
Tail call recursion
This one is a little tricky, because, now in late 2018, TC optimization is still an issue. But honestly – if you don't use any smart tricks to allow the default JS engine to use a really big numbers, it will get dizzy and claims that the next fibonacci number is "Infinity" by iteration 1477. The stack would probably overflow somewhere around iteration 10 000 (vastly depends on browser, memory etc…). Could be probably padded by try… catch block or check if "Infinity" was reached.
const fibonacciRTC = (n, i = 0, a = 0, b = 1) => {
console.log({
n: i,
fibonacci: a
});
if (n === 0) return;
return fibonacciRTC(--n, ++i, b, a + b);
}
fibonacciRTC(21)
It can be written as a one-liner, if we throe away the console.log thing and simply return a number:
const fibonacciRTC2 = (n, a = 0, b = 1) => n === 0 ? a : fibonacciRTC2(n - 1, b, a + b);
console.log(fibonacciRTC2(21))
Important note!
As I found out reading this mathIsFun article, the fibonacci sequence is valid for negative numbers as well! I tried to implement that in the recursive tail call form above like that:
const fibonacciRTC3 = (n, a = 0, b = 1, sign = n >= 0 ? 1 : -1) => {
if (n === 0) return a * sign;
return fibonacciRTC3(n - sign, b, a + b, sign);
}
console.log(fibonacciRTC3(8)); // 21
console.log(fibonacciRTC3(-8)); // -21
There is also a generalization of Binet's formula for negative integers:
static float phi = (1.0f + sqrt(5.0f)) / 2.0f;
int generalized_binet_fib(int n) {
return round( (pow(phi, n) - cos(n * M_PI) * pow(phi, -n)) / sqrt(5.0f) );
}
...
for(int i = -10; i < 10; ++i)
printf("%i ", generalized_binet_fib(i));
A quick way to get ~75
ty #geeves for the catch, I replaced Math.floor for Math.round which seems to get it up to 76 where floating point issues come into play :/ ...
either way, I wouldn't want to be using recursion up and until that point.
/**
* Binet Fibonacci number formula for determining
* sequence values
* #param {int} pos - the position in sequence to lookup
* #returns {int} the Fibonacci value of sequence #pos
*/
var test = [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,2971215073,4807526976,7778742049,12586269025,20365011074,32951280099,53316291173,86267571272,139583862445,225851433717,365435296162,591286729879,956722026041,1548008755920,2504730781961,4052739537881,6557470319842,10610209857723,17167680177565,27777890035288,44945570212853,72723460248141,117669030460994,190392490709135,308061521170129,498454011879264,806515533049393,1304969544928657,2111485077978050,3416454622906707,5527939700884757,8944394323791464,14472334024676221,23416728348467685,37889062373143906,61305790721611591,99194853094755497,160500643816367088,259695496911122585,420196140727489673,679891637638612258,1100087778366101931,1779979416004714189,2880067194370816120,4660046610375530309,7540113804746346429,12200160415121876738,19740274219868223167,31940434634990099905,51680708854858323072,83621143489848422977,135301852344706746049,218922995834555169026];
var fib = function (pos) {
return Math.round((Math.pow( 1 + Math.sqrt(5), pos)
- Math.pow( 1 - Math.sqrt(5), pos))
/ (Math.pow(2, pos) * Math.sqrt(5)));
};
/* This is only for the test */
var max = test.length,
i = 0,
frag = document.createDocumentFragment(),
_div = document.createElement('div'),
_text = document.createTextNode(''),
div,
text,
err,
num;
for ( ; i < max; i++) {
div = _div.cloneNode();
text = _text.cloneNode();
num = fib(i);
if (num !== test[i]) {
err = i + ' == ' + test[i] + '; got ' + num;
div.style.color = 'red';
}
text.nodeValue = i + ': ' + num;
div.appendChild(text);
frag.appendChild(div);
}
document.body.appendChild(frag);
You can get some cache to speedup the algorithm...
var tools = {
fibonacci : function(n) {
var cache = {};
// optional seed cache
cache[2] = 1;
cache[3] = 2;
cache[4] = 3;
cache[5] = 5;
cache[6] = 8;
return execute(n);
function execute(n) {
// special cases 0 or 1
if (n < 2) return n;
var a = n - 1;
var b = n - 2;
if(!cache[a]) cache[a] = execute(a);
if(!cache[b]) cache[b] = execute(b);
return cache[a] + cache[b];
}
}
};
If using ES2015
const fib = (n, prev = 0, current = 1) => n
? fib(--n, current, prev + current)
: prev + current
console.log( fib(10) )
If you need to build a list of fibonacci numbers easily you can use array destructuring assignment to ease your pain:
function fibonacci(n) {
let fibList = [];
let [a, b] = [0, 1]; // array destructuring to ease your pain
while (a < n) {
fibList.push(a);
[a, b] = [b, a + b]; // less pain, more gain
}
return fibList;
}
console.log(fibonacci(10)); // prints [0, 1, 1, 2, 3, 5, 8]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>fibonacci series</title>
<script type="text/javascript">
function generateseries(){
var fno = document.getElementById("firstno").value;
var sno = document.getElementById("secondno").value;
var a = parseInt(fno);
var result = new Array();
result[0] = a;
var b = ++fno;
var c = b;
while (b <= sno) {
result.push(c);
document.getElementById("maindiv").innerHTML = "Fibonacci Series between "+fno+ " and " +sno+ " is " +result;
c = a + b;
a = b;
b = c;
}
}
function numeric(evt){
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
var regex = /[0-9]|\./;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault)
theEvent.preventDefault();
}
}
</script>
<h1 align="center">Fibonacci Series</h1>
</head>
<body>
<div id="resultdiv" align="center">
<input type="text" name="firstno" id="firstno" onkeypress="numeric(event)"><br>
<input type="text" name="secondno" id="secondno" onkeypress="numeric(event)"><br>
<input type="button" id="result" value="Result" onclick="generateseries();">
<div id="maindiv"></div>
</div>
</body>
</html>
I know this is a bit of an old question, but I realized that many of the answers here are utilizing for loops rather than while loops.
Sometimes, while loops are faster than for loops, so I figured I'd contribute some code that runs the Fibonacci sequence in a while loop as well! Use whatever you find suitable to your needs.
function fib(length) {
var fibArr = [],
i = 0,
j = 1;
fibArr.push(i);
fibArr.push(j);
while (fibArr.length <= length) {
fibArr.push(fibArr[j] + fibArr[i]);
j++;
i++;
}
return fibArr;
};
fib(15);
sparkida, found an issue with your method. If you check position 10, it returns 54 and causes all subsequent values to be incorrect. You can see this appearing here: http://jsfiddle.net/createanaccount/cdrgyzdz/5/
(function() {
function fib(n) {
var root5 = Math.sqrt(5);
var val1 = (1 + root5) / 2;
var val2 = 1 - val1;
var value = (Math.pow(val1, n) - Math.pow(val2, n)) / root5;
return Math.floor(value + 0.5);
}
for (var i = 0; i < 100; i++) {
document.getElementById("sequence").innerHTML += (0 < i ? ", " : "") + fib(i);
}
}());
<div id="sequence">
</div>
Here are examples how to write fibonacci using recursion, generator and reduce.
'use strict'
//------------- using recursion ------------
function fibonacciRecursion(n) {
return (n < 2) ? n : fibonacciRecursion(n - 2) + fibonacciRecursion(n - 1)
}
// usage
for (let i = 0; i < 10; i++) {
console.log(fibonacciRecursion(i))
}
//-------------- using generator -----------------
function* fibonacciGenerator() {
let a = 1,
b = 0
while (true) {
yield b;
[a, b] = [b, a + b]
}
}
// usage
const gen = fibonacciGenerator()
for (let i = 0; i < 10; i++) {
console.log(gen.next().value)
}
//------------- using reduce ---------------------
function fibonacciReduce(n) {
return new Array(n).fill(0)
.reduce((prev, curr) => ([prev[0], prev[1]] = [prev[1], prev[0] + prev[1]], prev), [0, 1])[0]
}
// usage
for (let i = 0; i < 10; i++) {
console.log(fibonacciReduce(i))
}
I just would like to contribute with a tail call optimized version by ES6. It's quite simple;
var fibonacci = (n, f = 0, s = 1) => n === 0 ? f : fibonacci(--n, s, f + s);
console.log(fibonacci(12));
There is no need for slow loops, generators or recursive functions (with or without caching). Here is a fast one-liner using Array and reduce.
ECMAScript 6:
var fibonacci=(n)=>Array(n).fill().reduce((a,b,c)=>a.concat(c<2?c:a[c-1]+a[c-2]),[])
ECMAScript 5:
function fibonacci(n){
return Array.apply(null,{length:n}).reduce(function(a,b,c){return a.concat((c<2)?c:a[c-1]+a[c-2]);},[]);
}
Tested in Chrome 59 (Windows 10):
fibonacci(10); // 0 ms -> (10) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
JavaScript can handle numbers up to 1476 before reaching Infinity.
fibonacci(1476); // 11ms -> (1476) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]
Another implementation, while recursive is very fast and uses single inline function. It hits the javascript 64-bit number precision limit, starting 80th sequence (as do all other algorithms):
For example if you want the 78th term (78 goes in the last parenthesis):
(function (n,i,p,r){p=(p||0)+r||1;i=i?i+1:1;return i<=n?arguments.callee(n,i,r,p):r}(78));
will return: 8944394323791464
This is backwards compatible all the way to ECMASCRIPT4 - I tested it with IE7 and it works!
This script will take a number as parameter, that you want your Fibonacci sequence to go.
function calculateFib(num) {
var fibArray = [];
var counter = 0;
if (fibArray.length == 0) {
fibArray.push(
counter
);
counter++
};
fibArray.push(fibArray[fibArray.length - 1] + counter);
do {
var lastIndex = fibArray[fibArray.length - 1];
var snLastIndex = fibArray[fibArray.length - 2];
if (lastIndex + snLastIndex < num) {
fibArray.push(lastIndex + snLastIndex);
}
} while (lastIndex + snLastIndex < num);
return fibArray;
};
This is what I came up with
//fibonacci numbers
//0,1,1,2,3,5,8,13,21,34,55,89
//print out the first ten fibonacci numbers
'use strict';
function printFobonacciNumbers(n) {
var firstNumber = 0,
secondNumber = 1,
fibNumbers = [];
if (n <= 0) {
return fibNumbers;
}
if (n === 1) {
return fibNumbers.push(firstNumber);
}
//if we are here,we should have at least two numbers in the array
fibNumbers[0] = firstNumber;
fibNumbers[1] = secondNumber;
for (var i = 2; i <= n; i++) {
fibNumbers[i] = fibNumbers[(i - 1)] + fibNumbers[(i - 2)];
}
return fibNumbers;
}
var result = printFobonacciNumbers(10);
if (result) {
for (var i = 0; i < result.length; i++) {
console.log(result[i]);
}
}
Beginner, not too elegant, but shows the basic steps and deductions in JavaScript
/* Array Four Million Numbers */
var j = [];
var x = [1,2];
var even = [];
for (var i = 1;i<4000001;i++){
j.push(i);
}
// Array Even Million
i = 1;
while (i<4000001){
var k = j[i] + j[i-1];
j[i + 1] = k;
if (k < 4000001){
x.push(k);
}
i++;
}
var total = 0;
for (w in x){
if (x[w] %2 === 0){
even.push(x[w]);
}
}
for (num in even){
total += even[num];
}
console.log(x);
console.log(even);
console.log(total);
My 2 cents:
function fibonacci(num) {
return Array.apply(null, Array(num)).reduce(function(acc, curr, idx) {
return idx > 2 ? acc.concat(acc[idx-1] + acc[idx-2]) : acc;
}, [0, 1, 1]);
}
console.log(fibonacci(10));
I would like to add some more code as an answer :), Its never too late to code :P
function fibonacciRecursive(a, b, counter, len) {
if (counter <= len) {
console.log(a);
fibonacciRecursive(b, a + b, counter + 1, len);
}
}
fibonacciRecursive(0, 1, 1, 20);
Result
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
function fibo(count) {
//when count is 0, just return
if (!count) return;
//Push 0 as the first element into an array
var fibArr = [0];
//when count is 1, just print and return
if (count === 1) {
console.log(fibArr);
return;
}
//Now push 1 as the next element to the same array
fibArr.push(1);
//Start the iteration from 2 to the count
for(var i = 2, len = count; i < len; i++) {
//Addition of previous and one before previous
fibArr.push(fibArr[i-1] + fibArr[i-2]);
}
//outputs the final fibonacci series
console.log(fibArr);
}
Whatever count we need, we can give it to above fibo method and get the fibonacci series upto the count.
fibo(20); //output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
Fibonacci (one-liner)
function fibonacci(n) {
return (n <= 1) ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
Fibonacci (recursive)
function fibonacci(number) {
// n <= 1
if (number <= 0) {
return n;
} else {
// f(n) = f(n-1) + f(n-2)
return fibonacci(number - 1) + fibonacci(number - 2);
}
};
console.log('f(14) = ' + fibonacci(14)); // 377
Fibonacci (iterative)
function fibonacci(number) {
// n < 2
if (number <= 0) {
return number ;
} else {
var n = 2; // n = 2
var fn_1 = 0; // f(n-2), if n=2
var fn_2 = 1; // f(n-1), if n=2
// n >= 2
while (n <= number) {
var aa = fn_2; // f(n-1)
var fn = fn_1 + fn_2; // f(n)
// Preparation for next loop
fn_1 = aa;
fn_2 = fn;
n++;
}
return fn_2;
}
};
console.log('f(14) = ' + fibonacci(14)); // 377
Fibonacci (with Tail Call Optimization)
function fibonacci(number) {
if (number <= 1) {
return number;
}
function recursion(length, originalLength, previous, next) {
if (length === originalLength)
return previous + next;
return recursion(length + 1, originalLength, next, previous + next);
}
return recursion(1, number - 1, 0, 1);
}
console.log(`f(14) = ${fibonacci(14)}`); // 377

Categories

Resources