Working on a JavaScript problem regarding Fibonacci numbers from a codewars challenge here
Here is my code so far:
function productFib(prod){
let firstFib = 0;
let secondFib = 1;
while (prod > firstFib * secondFib){
firstFib = firstFib + secondFib
secondFib = firstFib + secondFib
}
if (prod === firstFib*secondFib){
return [firstFib, secondFib, true]
} else {
firstFib = secondFib - firstFib;
secondFib = secondFib - firstFib;
return [firstFib, secondFib, false]
}
}
I have passed all tests except two: productFib(193864606) and productFib(602070). My results are [10946, 17711, false] and [610, 987, false] respectively, and they should say true instead of false. But if you multiply those Fibonacci numbers they equal the prod param, so I don't understand why my conditional statement isn't catching those two specifically.
Your logic needs tiny change. The way you are getting your pairs is :
function productFib(prod){
let firstFib = 0;
let secondFib = 1;
while (prod > firstFib * secondFib){
firstFib = firstFib + secondFib
secondFib = firstFib + secondFib
console.log(firstFib,secondFib);
}
if (prod === firstFib*secondFib){
return [firstFib, secondFib, true]
} else {
firstFib = secondFib - firstFib;
secondFib = secondFib - firstFib;
return [firstFib, secondFib, false]
}
}
productFib(602070);
Your pairs are :
0,1
1,2
3,5
But you are missing the cases when 2,3 or 1,1 should be together.
That is because you are updating firstFib as firstFib + secondFib. Instead of that it should take the value of secondFib directly
function productFib(prod){
let firstFib = 0;
let secondFib = 1;
while (prod > firstFib * secondFib){
let prevFirstFib = firstFib;
firstFib = secondFib;
secondFib = prevFirstFib + secondFib;
console.log(firstFib, secondFib);
}
if (prod === firstFib*secondFib){
return [firstFib, secondFib, true]
} else {
firstFib = secondFib - firstFib;
secondFib = secondFib - firstFib;
return [firstFib, secondFib, false]
}
}
console.log(productFib(602070));
console.log(productFib(193864606));
There are two issues:
The first loop jumps 2 Fibonacci steps in each iteration. But what was the greatest Fibonacci number of the two should remain, and be used as the least of the two.
The else part should not backtrack to a previous pair. The current pair is what you need to return. So you can do this without if..else even, and pass as boolean argument the equality check.
Correction:
function productFib(prod){
let firstFib = 0;
let secondFib = 1;
while (prod > firstFib * secondFib){
[firstFib, secondFib] = [secondFib, firstFib + secondFib]
}
return [firstFib, secondFib, prod === firstFib*secondFib]
}
const assertSimilar = (a, b) => console.assert(JSON.stringify(a) === JSON.stringify(b));
assertSimilar(productFib(4895), [55, 89, true])
assertSimilar(productFib(5895), [89, 144, false])
assertSimilar(productFib(74049690), [6765, 10946, true])
assertSimilar(productFib(84049690), [10946, 17711, false])
assertSimilar(productFib(193864606), [10946, 17711, true])
assertSimilar(productFib(447577), [610, 987, false])
assertSimilar(productFib(602070), [610, 987, true])
console.log("tests passed");
If you throw some logging statements in, it will be a lot easier to see what's going on. Your function actually fails with a much smaller number - 40. Putting in some logging, let's see what's happening:
function productFib(prod){
let firstFib = 0;
let secondFib = 1;
while (prod > firstFib * secondFib){
console.log("before", firstFib, secondFib);
firstFib = firstFib + secondFib
secondFib = firstFib + secondFib
console.log("after", firstFib, secondFib);
}
console.log(prod, firstFib, secondFib)
if (prod === firstFib*secondFib){
return [firstFib, secondFib, true]
} else {
firstFib = secondFib - firstFib;
secondFib = secondFib - firstFib;
return [firstFib, secondFib, false]
}
}
console.log(productFib(40))
As you can see, it's skipping a number. Rather than using the previous secondFib as the new firstFib it's skipping it altogether, that's why your function is failing. A simple way to fix this is to save off the previous firstFib value, set firstFib = secondFib and then set secondFib = prevFirst + secondFib, like so:
function productFib(prod){
let firstFib = 0;
let secondFib = 1;
while (prod > firstFib * secondFib){
console.log("before", firstFib, secondFib);
let prevFirst = firstFib;
firstFib = secondFib
secondFib = prevFirst + secondFib
console.log("after", firstFib, secondFib);
}
console.log(prod, firstFib, secondFib)
if (prod === firstFib*secondFib){
return [firstFib, secondFib, true]
} else {
firstFib = secondFib - firstFib;
secondFib = secondFib - firstFib;
return [firstFib, secondFib, false]
}
}
console.log(productFib(40))
Now you'll see that it's stepping through the numbers correctly and outputting what you expect!