Can anyone explain how this block of code works? - javascript

function f(num) {
if (num<1) {
return 1;
}
return f(num-1) + f(num-2);
}
f(5); // 13
I investigated this code in the debugger but it's still unclear to me how it works. I see it as some kind of recursion, but don't get it at all.
Any kind of help will be appreciated.

There are essentially two forms of recursion direct and indirect. However, in either case any proper form of recursion must abide by three rules which makes it recursive.
1.) A recursive algorithm must have a base case.
2.) A recursive algorithm must change its state and move toward the base case.
3.) A recursive algorithm must call itself, recursively.
The intention for using a recursion algorithms focuses on taking a relatively mid to large problems and breaking them into smaller problems which can be solved iteratively or until the "base case" condition has been proven true.
function f(num) {
if (num<=1) { // (1) Base case condition
return 1; // (2.b) moving forward once the base case is true
}
// (3) the function calling itself
// also (2.a) changed state - (i.e., the param value is being decremented or "unwound" with each pass of recursion (i.e., method call)
return f(num-1) + f(num-2);
}
f(5); // Fn = Fn-1 + Fn-2 (Fibonacci Number Series)
Resources:
https://www.geeksforgeeks.org/recursion/
https://medium.com/launch-school/recursive-fibonnaci-method-explained-d82215c5498e
https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/the-factorial-function
https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/recursive-factorial
https://runestone.academy/runestone/books/published/pythonds/Recursion/TheThreeLawsofRecursion.html
https://www.natashatherobot.com/recursion-factorials-fibonacci-ruby/

It is a simple recursion implementation of calculating the num-th Fibonacci number(1 1 2 3 5 8....). And it has a small bug. It should be:
function f(num) {
if (num<=1) { // should be <= 1 instead of <, to handle when num = 1, otherwise it'll end up with f(0)+f(-1)
return 1;
}
return f(num-1) + f(num-2);
}
You can try to write down by hand and simulate some simple cases, which I think is really helpful when you study algorithms.
For example:
f(0) -> 0 is less than 1, return 1, thus f(0) = 1
f(1) -> 1 is less than or equal to 1, return 1, thus f(1) = 1
f(2) -> 2 is greater than 1, return f(1) + f(0), which we know from above, is 1 + 1, thus f(2) = 2
f(3) -> 3 is greater than 1, return f(2) + f(1), 2 + 1, thus f(3) = 3
f(4) -> 4 is greater than 1, return f(3) + f(2), 3 + 2, thus f(4) = 5
I bet you see the patterns now. Hope it helps.

It is recursion. It's a fibonacci series. Step through it slowly.
Start with a simple example:
f(0) = 1 (as num <1)
Increase to 1
f(1) = f(0) + f(-1) = 2
(as num = 1, but f(num-1) and f(num-2) are both less than 1 (and so each return 1)
increase to 2:
f(2) = f(2-1) + f(0) = f(1) + f(-1) = 3
we've solved f(1) and f(-1) already so we know the total returned is 2
increase to 3:
f(3) = f(3-1) + f(3-2) = f(2) + f(1) = 3 + 2 = 5
Remembering that the algorithm is expanding out each step fully (not relying on previous solutions so to speak). so this last example would look more like:
f(3) = f(2) + f(1) = (f(1) +f(0)) + (f(0)+f(-1)) = (f(0) + f(-1)) + 1 + 1 + 1 = 1 + 1 + 1 + 1 + 1 = 5

Related

Recursive Functions Runtime 2^n - 1

I have the following function fn(n).
function fn(n) {
if (n < 0) return 0;
if (n < 2) return n;
return fn(n - 1) + fn(n - 2);
}
I understand how this code works, but don't how to calculate time complexity for it.
Let’s do some examples:
For n = 3, you have 5 function calls. First fn(3), which in turn calls fn(2) and fn(1) and so on.
For n = 4, you have 9 function calls. First fn(4), which in turn calls fn(3) and fn(2) and so on.
Graphical representation of the 2 examples:
The leftmost nodes go down in descending order: fn(4), fn(3), fn(2), fn(1), which means that the height of the tree (or the number of levels) on the tree will be n.
The time complexity of this code is 2^n - 1. Although, if we count all calls will be just 9 calls for n = 4.
And the question is how we get 2^n - 1? I don't understand
One of the ways of calculating recursive algorithm's time complexity is using the Recursion Tree Method. For this particular case, we can write T(n)=T(n-1)+T(n-2)+2*O(1), where O(1) means constant time, since we have two comparison checks of n values using if. The recursion tree would look something like this:
1 n
2 (n-1) (n-2)
4 (n-2) (n-3) (n-3) (n-4)
8 (n-3)(n-4) (n-4)(n-5) (n-4)(n-5) (n-5)(n-6)
...
2^i for i-th level
Total work done will be the sum of all of the work done in each level, so we can write T(n)=1 + 2 + 4 + 8 + 16 + 32 + ... = 2^0 + 2^1 + 2^2 + 2^3 + 2^4 + ... + 2^i. This is a geometric series which means that the T(n) is equal to (1-2^n)/(1-2) = (1-2^n)/(-1) = 2^n - 1. Because of that the time complexity of the function fn(n) is O(2^n).
You could also approach this using Back Substitution method. We know the following:
T(0)=1
T(1)=1
T(2)=1
T(n)=T(n-1)+T(n-2)+2*O(n)≈2*T(n-1)
Substituting T(n-2) with T(n-1) is allowed. In doing so you will get a higher bound which is still true for T(n-1)+T(n-2).
After the substitution you can also write T(n-1)=2*T(n-2), T(n-2)=2*T(n-3), ...
Using these values and substituting them recursively in to the T(n) you will get:
T(n)=2*2*T(n-2)
=2*2*2*T(n-3)
=2*2*2*2*T(n-4)
=...
=2^i * T(n-i)
From there you can write n-i=1 => i=n-1 and substitute the i value in T(n). You can do this because T(1)=1 is one of the base conditions.
=> T(i)=2^(n-1) * T(n-(n-1))=2^(n-1) * T(n-n+1)=2^(n-1) * T(1)=2^(n-1)
This means that the time complexity is O(2^n).

Javascript: How to recursively return a counter?

In the example below, I don't want to make a counter as a param. Rather, I just want to return '+ 1' each time so that what gets returned is the number of steps it takes. My issue lies with the base case. If I do return + 1, I get the correct number of steps plus one additional step so I tried just return but that delivers NaN. Is it even possible?
var numberOfSteps = function(num) {
if (num == 0) {
return;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
};
edit : The goal is to track how many steps it takes to reduce a number to 0. If it's even, divide by 2 or else subtract by 1. Ultimately, I want to return the number of steps it takes for any given number to get reduced to 0 following those rules
I hope the point has gotten through in the long comment thread and other answers that return + 1 is equivalent to return (+1), that is, return the integer positive one. And since there are no steps to take once you've reached zero, +1 is the wrong answer. Similarly, a plain return is functionally equivalent to return undefined. But undefined is not a number, and you're going to run into problems if you later try to add 1 to it. So the solution from the comments or other answers to return the correct number of steps, which in this case 0, will fix your code.
I would like to point out another way to solve this, though:
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (n % 2 == 0 ? n / 2 : n - 1)
console .log (numberOfSteps (12))
There are superficial differences here from the other solutions, such as using an arrow function, using a conditional statement (ternary) rather than if-statements, and using <= 0 instead of < 0 to avoid possible infinite loops on negative numbers.
But the fundamental difference is that this code only has one recursive branch. I think this is a better match to the problem.
We can think of this as a function which answers "How many steps does it take to reach 0 from our input number if each step cuts even numbers in half and subtracts one from odd ones?" Well that logically leads to a base case (we're already at 0) so have to return 0, and a recursive one (we're at some positive integer) so have to add 1 to the total steps required from our next entry.
By doing this single recursive call and adding one to the result, we make it clearer what the recursion is doing.
If this is unclear, then this alternative might show what I mean:
const takeStep = (n) =>
n % 2 == 0 ? n / 2 : n - 1
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (takeStep (n))
Think you just need to return 0 when it's...zero.
var numberOfSteps = function(num) {
if (num == 0) {
return 0;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
}
return + 1 maybe doesn't do what you think it does: it returns the number 1. + here means positive not negative, there is no addition or subtraction going on. It will also give you one too many steps.
return; by itself returns undefined, which when converted to a Number, translates to NaN, because, well, it's not a number.

javascript: understanding the flow of a fibonacci recursive statement

I eventually want to get the hang of dynamic programming but before that, I am having a hard time understanding the flow of this. I understand recursion but I'm having trouble understanding the flow of this:
function fib(n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fib(n - 1) + fib(n - 2);
}
console.log(fib(3));
if I have a small integer of 3, it does not pass those 2 conditionals so it hits return fib(n-1)+fib(n-2); So to my understanding, that will go through the first part of that first: fib(n-1) (3-1 = 2)... 2 does not satisfy either of those conditionals so it runs fib(n-1) (2-1 = 1). 1 DOES satisfy one of the conditionals so it returns 1 and breaks that part of it.
Now to to the next part: fib(n-2) . (3-2 = 1). 1 does satisfy one of the conditionals so it returns 1 .
So in the end, isn't that returning 1 + 1 ?
I'm not sure where I'm going wrong in my understanding.
You are correct in that fib(3) should return 2, because 2 is the 3rd number in the Fibonacci sequence (starting at 0)
It helps to write out it out as tree:
fib(3)
/ \
fib(2) fib(1)
/ \ \
fib(1) fib(0) 1
/ \
1 0
above you can see how each recursive call goes all the way to 0 or 1 before returning a result back up the previous layer.
One of my favorite ways to do this is to start with the base cases and go backwards:
fib(0); // => 0
fib(1); // => 1
Then we get to the default case:
fib(2); // == fib(1) + fib(0) == 1 + 0 ==> 1
fib(3); // == fib(2) + fib(1) == 1 + 1 ==> 2
fib(4); // == fib(3) + fib(2) == 2 + 1 ==> 3
This is much easier than trying to figure out fib(4) first since you need to nest. Looking at the function it's easy to see what to try.
Also know that calls to the same function doesn't get any special treatment. It runs until it returns with a value and it's arguments and local variables are local to the call so every fib call has its own n and it waits for the two calls to return to sum the results.

javascript making change algorithm

I'm solving this problem "Making change" in javascript:
Question:
Given an amount of money, an array of coin denominations, compute the
number of ways to make the amount of money with coins of the available
denominations.
Example:
For amount=4 (4¢) and denominations=[1,2,3] (1¢,
2¢ and 3¢), your program would output 4—the number of ways to make
4¢ with those denominations:
1¢, 1¢, 1¢, 1¢
1¢, 1¢, 2¢
1¢, 3¢
2¢, 2¢
I found a solution:
var makeChange = function(total){
var count = 0;
var coins = [1, 2, 5, 10, 20, 50, 100, 200];
var changer = function(index, value){
var currentCoin = coins[index];
if( index === 0){
if( value % currentCoin === 0){
count++;
}
return;
}
while( value >= 0 ){
changer(index-1, value);
value -= currentCoin;
}
}
changer(coins.length-1, total);
return count;
};
makeChange(200);
Problem(s):
Can someone explain to me what is going on? I tried following the code but i get lost in between the recursion.
I understand that he is taking the final coin value and he is substracting from the given total. (But why?) I'm kinda lost.
When value >= 0 in the while loop, It keeps looping around increasing the index, i couldn't understand why.
Can someone make sense out of this algorithm?
Sorry, just started learning Dynamic Programming.
Thank you,
Let's track what happens with makeChange(4):
The function changer gets defined then called for the first time.
value = 4, index = 7, coins[7] = 200
Since the variable, index is not 0, we move on to the while loop.
A second call to changer is made with index 6
Meanwhile, the first call continues the 'while'
loop but since 200 has been subtracted from 'value',
'value' is now less than 0 so the 'while' loop terminates
and this first call does nothing more.
(Keep in mind that the variable 'value' is distinct
and private to each call, so the 'while' loop only
affects the 'value' in its own function call.)
Ok, now this pattern continues with all the function calls that have index pointing to a coin larger than value until index is 1.
value = 4, index = 1, coins[1] = 2
This time more happens in the while loop:
We get the function call, 'changer(0,4)',
AND a second function call, 'changer(0,2)',
after we subtract 2 from 'value', which was 4,
AND a third function call, 'changer(0,0)',
after we subtract 2 from 'value', which was 2.
These 3 calls respectively represent:
1 + 1 + 1 + 1
2 + 1 + 1
2 + 2
Each time the line 'value -= currentCoin' is executed,
it represents the start of another set of choices for
solutions that include that coin.
4 % coins[0] = 0, meaning 4 is divisible by 1 represents 1 + 1 + 1 + 1
4 - 2 folllowed by 2 % 1 represents 2 + 1 + 1
and 4 - 2 - 2 represents 2 + 2
Total count: 3

Explain, please, these ++ and -- operations

Why this code outputs 3, not 2?
var i = 1;
i = ++i + --i;
console.log(i);
I expected:
++i // i == 2
--i // i == 1
i = 1 + 1 // i == 2
Where I made mistake?
The changes occur in this order:
Increment i (to 2)
Take i for the left hand side of the addition (2)
Decrement i (to 1)
Take i for the right hand side of the addition (1)
Perform the addition and assign to i (3)
… and seeing you attempt to do this gives me some insight in to why JSLint doesn't like ++ and --.
Look at it this way
x = (something)
x = (++i) + (something)
x = (2) + (something)
x = (2) + (--i)
x = (2) + (1)
The terms are evaluated from left to right, once the first ++i is evaluated it won't be re-evaluated when you change its value with --i.
Your second line is adding 2 + 1.
In order, the interpreter would execute:
++i // i == 2
+
--i // i == 1
i = 2 + 1
++i equals 2, `--i' equals 1. 2 + 1 = 3.
You're a little off on your order of operations. Here's how it goes:
i is incremented by 1 (++i) resulting in a value of 2. This is
stored in i.
That value of two is then added to the value of (--i)
which is 1. 2 + 1 = 3
Because when you use ++i the value of i is incremented and then returned. However, if you use i++, the value of i is returned and then incremented. Reference
++$a Increments $a by one, then returns $a.
$a++ Returns $a, then increments $a by one.
--$a Decrements $a by one, then returns $a.
$a-- Returns $a, then decrements $a by one.
Because you're expecting this code to work as if this is a reference object and the values aren't collected until the unary operations are complete. But in most languages an expression is evaluated first, so i returns the value of i, not i itself.
If you had ++(--i) then you'd be right.
In short, don't do this.
The result of that operation isn't defined the same in every language/compiler/interpreter. So while it results in 3 in JavaScript, it may result in 2 elsewhere.

Categories