I'm learning the recursion concept in js, I got a very basic question of the base code returning problem.
function factorial(n) {
if (n === 1) {
return 1;
}
return n * factorial(n - 1);
}
So this is a simple factorial example of explaining the recursion.
factorial(5) = 120
My question is, why it's not returning 1 when the n reaches 1? After the return inside the if statement, the second return will continue to run? And if it return 1, the second return continue to run and it will do 5 * 1 forever (let's say n reaches 5)???
I made a small example, adding some log's. The attribute indent was added to help on logs indentation, and for better understand what's happen.
On recursive calls (like on non recursive calls), when outer function calls the inner function, the current variables are stored somewhere on memory (on one stack), and then call the function.
When the inner function returns, the values will be restored.
If you see the log's of my example, the parameter n decrease the value on each call, but was restored after the inner function returns.
Answering to your questions:
My question is, why it's not returning 1 when the n reaches 1?
when the n reaches 1, the function returns 1, but that result will applied on de factorial(2), that are waiting at that moment for the result, and so on.
After the return inside the if statement, the second return will continue to run?
Yes, the second if statement will continue to run, but it's like on other instance, that was waiting for the result.
And if it return 1, the second return continue to run and it will do 5 * 1 forever (let's say n reaches 5)???
No. The n will be multiplied with the result of next call (the outer call waits for the inner call):
5 * factorial(4)
4 * factorial(3)
3 * factorial(2)
2 * factorial(1)
1
2 * 1 = 2
3 * 2 = 6
4 * 6 = 24
5 * 24 = 120
function factorial(n, indent) {
if (!indent) indent = '';
console.log(indent+'BEGIN: factorial('+n+')');
if (n === 1) {
console.log(indent+'END: factorial('+n+'): 1');
return 1;
}
let factorialNMinus1 = factorial(n - 1, indent + ' ');
let result = n * factorialNMinus1 ;
console.log(indent+'END: factorial('+n+'): ' + n + ' * ' + factorialNMinus1 + ' = ' + result);
return result;
}
console.log('result = ' + factorial(5));
A good way of analyzing recursion is by using a simple situation, and think how the recursion will unfold.
Lets say n = 3.
function factorial(n) {
if (n === 1) {
return 1;
}
return n * factorial(n - 1);
}
console.log(factorial(3));
So, the following iterations will happen:
fac(3) == 3 * fac(3-1)
fac(3-1) == 3-1 * fac(2-1)
fac(2-1) == 2-1 * 1
The condition that makes the recursion unfold and start returning is n == 1, so when that happens, the last function call will return 1 instead of calling itself again.
But the actual result will be the sum of all returned operations: (3 * ((3-1) * ((2-1) * 1)))
So, factorial(5) returns 120 because: (5 * ((5-1) * ((4-1) * ((3-1) * ((2-1) * 1))))) == 120.
Related
Gif for the debugger in console
So, when running this, i'm a bit confused how fac parameter is maintaing the state. what i understand by factorial(4) is
4 * (4-1) // 4 * 3 = 12
12 * (3-1) // 12 * 2 = 24
24 * (2-1) // 24 * 1 = 24
function factorial(fac){
debugger
if(fac == 1)
return fac
return fac * factorial(fac-1)
}
factorial(4)
Every call to factorial has its own fac parameter, with its own value. So when, in the first call (during factorial(4)), when you do:
return fac * factorial(fac - 1);
that calls factorial again, passing in the value resulting from fac - 1 (3). That new call receives fac = 3 and does its work with it. While that's happening, the first call is waiting to get the return value from it (let's call it retVal) so it can finish the return fac * ____________ by plugging retVal in where ____________ is.
Eventually, a call to factorial does its work by returning fac instead of calling factorial again, which means the one that called it can complete its work and return its return value, which means the one that called it can do that, until we get back to the top one that returns the overall result.
Here's an attempt to show how the calls stack up (using indentation for showing the recursive calls):
factorial(fac = 4)
factorial(fac = 3)
factorial(fac = 2)
factorial(fac = 1)
return 1
|
v
return 2 * 1 = 2
|
+−−−−−−−+
|
v
return 3 * 2 = 6
|
+−−−−−−−+
|
v
return 4 * 6 = 24
Note that when factorial(1) is running, there are four different fac parameters in memory, fac = 4 (the outermost call), fac = 3 (the first recursive call), fac = 2 (the next recursive call), and fac = 1 (the last recursive call before the returns kick in).
Think of the function calls as stack, so when fac(4) is called this stack is formed
factorial(1)
^
Calls^
^
factorial(2)
^
Calls^
^
factorial(3)
^
Calls^
^
factorial(4)
then this stack is resolved from top down. so value of fac is being changed at every call
factorial(1) ==> fac = 1, return value =1
then resolves
factorial(2) ==> fac = 2, return value =2*factorial(1) > already in memory
then resolves
factorial(3) ==> fac = 3, return value =3*factorial(2) -> in memory
then resolves
factorial(4) ==> fac = 4, return value =4*factorial(3) -> in memory
You can simplify pure expressions the same way you can simplify mathematical expressions.
factorial(4)
= 4 * factorial(4 - 1) // because 4 != 1
= 4 * factorial(3)
= 4 * (3 * factorial(3 - 1)) // because 3 != 1
= 4 * (3 * factorial(2))
= 4 * (3 * (2 * factorial(2 - 1))) // because 2 != 1
= 4 * (3 * (2 * factorial(1)))
= 4 * (3 * (2 * 1)) // because 1 == 1
= 4 * (3 * 2)
= 4 * 6
= 24
This is a very powerful way of reasoning about expressions. It's one of the advantages of writing pure code instead of impure code. You can't simplify impure expressions in this manner because impure code has side effects which need to be tracked.
Anyway, why don't you try to simplify the following result expression by yourself? It'll help you understand how recursion works in functional programs. No need to think about function call stacks or anything else technical. Just get a pen and paper and start simplifying the expression like you would do in your 5th grade math class.
function fib(n) {
if (n === 0) return 1;
if (n === 1) return 1;
return fib(n - 1) + fib(n - 2);
}
const result = fib(5);
console.log(result); // 8
A few tips to remember.
When replacing a function call with its result, wrap it in parentheses.
Always simplify the leftmost expression first. This mimics the way JavaScript works.
Simplify expressions one at a time. Don't simplify multiple expressions in a single step.
I'm learning to work with recursion and so far it went well with basic examples. However I want to calculate the factorial, but I don't understand what happened step-by-step. If I do it imperatively I understand it but I fail on this example:
return x * fac(x-1); gives me back 5 * 4, so far soo good, but what happens now? Does it mean it become 20 now? So my next iteration would be then 20 * 19?
const fac = (x) => {
if(x <= 1) {
return x;
}
return x * fac(x-1);
};
console.log(fac(5)); // 120
just walk through the logic.
1. fac(5) yields 5 * fac(4)
2. fac(4) yields 4 * fac(3)
3. fac(3) yields 3 * fac(2)
4. fac(2) yields 2 * fac(1)
5. fac(1) yields 1
substituting from bottom to top, you get
fac(5) = 5 * 4 * 3 * 2 * 1
I think i understand that part now and the difference between 4 and fac(4). The steps look like:
5. 5 * // ()
4. 4 * // (20)
3. 3 * // (60)
2. 2 * // (120)
1. 1 * // (120)
However, I have another example which i cant resolve step by step, while i can see the logic in the imperatively programming.
let fibo = (x) => {
if(x<=2) {return 1;}
return fibo(x-1) + fibo(x-2);
};
console.log(fibo(4)); //3
I cant resolve step by step what return fibo(x-1) + fibo(x-2); values this gives me each step. On the imperatively programming it is
function fibonacci(num){
var a = 1, b = 0, temp;
while (num >= 1){
temp = a;
a = a + b;
b = temp;
num--;
}
return b;
}
console.log(fibonacci(4); // 3
where the steps would be like
4. b = 1
3. b = 1
2. b = 2
1. b = 3
I wanted someone to basically help me understand what each line of code is doing and help me comment each line (if applicable) so that it can help explain to another person what it's doing. It'd be awesome if one can just give second eyes and ensure that the code is actually good - I'm trying to get my head around Factorial/Recursion, and did some research and found these solutions for this.
I was given this scenario:
For positive n, factorial is n! = n(n−1)! (e.g. 5! = 5 * 4
* 3 * 2 * 1)*
Here's what I've found for this scenario:
// Prompt user to enter a number to calculate the factorial
var num = prompt("What number do you want to find the factorial of?");
var factorial = function(n) {
if (n == 0) {
return 1;
} else {
product = 1;
for (i = 1; i < n; i++) {
product *= i;
}
return product;
}
}
console.log(factorial(num));
Recursive
Create a recursive algorithm to calculate the factorial using every second
number as shown in examples below:
5! = 5 * 3 * 1 = 15
6! = 6 * 4 * 2 = 48
As for the cursive part, this is added onto the above code and is written in the following -
// recursive
var factorial = function(n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
console.log(factorial(num));
Would appreciate your assistance on this - Apologies if this has already been answered, please direct me to another thread if this has been already posted. Thanks!
You don't need recursion for that:
/**
* Calculate factorial, optionally using a difference other than 1 with previous value.
* Example: factorial(6, 2) // 6*4*2 = 48
*/
var factorial = function(n, d) {
if (!d) {d = 1;}
var product = 1;
while (n > 1) {
product *= n;
n -= d;
}
return product;
};
console.log(factorial(6, 2)); // 48
console.log(factorial(6)); // 720
Note: Declare local variables inside the function with keyword 'var'. Otherwise they become globals and the second time you attempt to use a function may produce wrong results.
Usually, writing a function for Factorial is an exercise on writing recursive function. The first example code is not recursive and just an overly complicated way of calculating a factorial by multiplying the numbers iteratively so I'll skip that.
The second code is recursive, and it is following the recursive definition of factorial in your usual mathematics:
f: N => N, f(x) = x! = { x < 1 : 1, else : x (x - 1)! }
Or equivalently in JavaScript:
let fac = n => n < 1 ? 1 : n * fac(n - 1);
An expansion of an example computation would look like:
5!
5(4!)
5(4(3!))
5(4(3(2!)))
5(4(3(2(1))))
5(4(3(2(1(0!)))))
5(4(3(2(1(1)))))
120
So, I'm just starting to explore recursion and am a little stuck on a concept. Here is a solution I located for a sum digits function ( f(126) = 1 + 2 + 6 = 9 ):
function sumDigits(num, sum){
if (num === 0) {
return sum;
} else {
sum += num % 10;
num = Math.floor(num / 10);
return sumDigits(num, sum);
}}
I traced it down to the base, so far everything makes sense:
**Trace**
f(126, 0)
{
sum = 6
num = 12
f(12, 6)
}
f(12, 6)
{
sum = 8
num = 1
f(1, 8)
}
f(1, 8)
{
sum = 9
num = 0
f(0, 9)
}
f(0, 9) = 9
I guess what doesn't make sense to me is HOW the base case is being passed back through during unwinding? How exactly is it traveling?
I'm expecting a facepalm, but until I understand I don't think I could replicate this solution.
Thanks for your help!
The sum is accumulated and passed forward in each call to sumDigits. It's this value that's returned whenever the first argument equals 0. I find that it helps to write out the recursion explicitly:
sumDigits(123, 0);
return sumDigits(12, 3);
return sumDigits(1, 5)
return sumDigits(0, 6) // the base case (sum = 6)
return sum;
The final call returns 6. The previous call returns the result of the final call. The call before that returns the call before the final call (and so on). So they all end up unraveling the final sum.
Note that each call returns the result of the next call in the chain. What stops this is the base case (i.e. a condition that results in the return of a concrete value (i.e. no additional calls)).
I'd suggest
function sumDigits(num) {
if (num < 0)
return sumDigits(Math.abs(num)) //handle negative numbers
least_sig_digit = num % 10
if (num < 10)
return least_sig_digit //in case num is a float)
else
return least_sig_digit + sumDigits(Math.floor(num / 10))
}
This way you will drill down until sumDigits returns the base case, and then bubble the result. By the time you reach the top of the call stack, you should have the sum of all digits.
Here's how this works:
sumDigits(126)
= 6 + sumDigits(12)
= (6+2) + sumDigits(1)
= (6+2+1)
= 9
The function calls are made from top-to-bottom order.
The return value bubbles up in bottom-to-top order, eventually returning the value 9 for the expression sumDigits(126).
The best way to think about recursion is defining the behavior to move from one layer to the next, and not worry about the big picture. As long as you're satisfied when someone tells you 5! = 5*4!, it's a lot easier to conceptualize recursion.
What is sumDigits(126)? It's 6 + sumDigits(12). But what is sumDigits(12)? It's (6+2) + sumDigits(1). etc.
It's returning sum += num % 10 recursively.
Another way to think about it, it's returning sum but each call modifies sum (the += operator) such that when it gets to the base case the value of sum in the innermost loop is the actual sum. So just return that value through all the returns.
If you just want to print you don't even need to return anything. Just have the base case print the value of sum and return null.
The summing is done on the way in to the base case, not on the way out.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Can someone explain how this recursive function produces 5 * 4 * 3 * 2 * 1 to get 120?
var factorial = function(n){
if (n === 0)
return 1;
else
return n * factorial(n - 1);
};
factorial(5); // spits out 120
If we use 5 like like in the example, once we got to the else statement wouldn't
return n * factorial(n - 1);
translate to 'return 5 multiplied by the factorial function(5-1); 5 times...
Am I wrong to feel this recursive function feels like a 'for loop?'
No, recursion and loops have a lot in common. In particular, it's very important that they both have a termination condition. :-) In this case, that termination condition is n === 0.
The best way to understand this is to single-step through the code in a debugger. Your browser has one, so you could put that code in a page and load it and walk through it.
To get you started:
You call factorial(5). Since n is not === 0, factorial calls itself with n - 1 (4)
Now we've recursed one level, and we're running factorial(4) (the call to factorial(5) still hasn't returned, it's waiting on us). Since n is not === 0, we call factorial(3) and wait for it to return.
...rinse, repeat until factorial(0) is called. Since n === 0 is true (at that point, there are five calls to factorial outstanding and stacked up), factorial(0) returns 1, and we can start unwinding the stacked up calls.
Now factorial(1) can finish by multiplying the result it got from factorial(0) by its copy of n (1) and returning that.
...which lets factorial(2) finish and multiply that by 2...
...rinse repeat...
Or to put it another way showing the nesting (recursion):
factorial(5)
return 5 * factorial(4)
return 4 * factorial(3)
return 3 * factorial(2)
return 2 * factorial(1)
return 1 * factorial(0)
return 1
And because you can't get enough diagrams (or at least I can't):
factorial(5) factorial(4) factorial(3) factorial(2) factorial(1) factorial(0)
calls ---------->
calls ---------->
calls ---------->
calls ---------->
calls ----------->
n is 0, so
returns 1
|
returns 1 * 1<-----------+
= 1
|
returns 2 * 1<------------+
= 2
|
returns 3 * 2<------------+
= 6
|
returns 4 * 6<------------+
= 24
|
returns 5 * 24<-----------+
= 120
Result: 120
Side note: That function doesn't allow for negative numbers; it could probably use a guard at the beginning...
The n changes:
5 * factorial(5-1) = 5 * 4 * factorial(4-1) = 5 * 4 * 3 * factorial(3-1) = 5 * 4 * 3 * 2 * factorial(1-1) = 5 * 4 * 3 * 2 * 1
Also to make this function better you could stop it when n is equal to 1, since the factorial of 1 is 1:
var factorial = function(n){
if (n === 1 || n === 0)
return 1;
else
return n * factorial(n - 1);
};
This function says: if you want to calculate factorial(5), well, that's really just
5 * factorial(4)
and if you want to calculate factorial(4), that's really just 4 * factorial(3)
5 * 4 * factorial(3)
and the thing about factorial(3) is that it's really just 3 * factorial(2)
5 * 4 * 3 * factorial(2)
and so on. But when you get down to factorial(0), the function finally stops (because of the if n == 0 case) and returns 1, without any further recursion. So you get
5 * 4 * 3 * 2 * 1
return n * factorial(n - 1) translates to (on the first run), "return (5 * 4!)". It doesn't do anything 5 times.
If we use 5 like like in the example, once we got to the else statement wouldn't
return n * factorial(n - 1);
translate to 'return 5 multiplied by the factorial function(5-1); 5 times...
No, it would translate to 'return n multiplied by the factorial function (n-1)' (5 times, because n starts at 5, decrements and enters the else clause until it reaches 0).
When you first enter the function, n is equal to 5.
The if clause checks if n is equal to 0. It isn't, so it goes to:
The else clause. Which translates to 'return 5 multiplied by the factorial function (which you're in) (5 - 1).
When you enter the factorial function, n is now 4.
Repeat all of those steps until n is equal to 0. The if clause will then be true and the function will return 1.
So 1 is returned from factorial(0). Factorial(1) returns 1 * factorial(0), so 1 * 1 = 1.
Factorial(2) returns 2 * factorial(1), so 2 * 1 = 2.
Factorial(3) returns 3 * factorial(2), so 3 * 2 = 6.
Factorial(4) returns 4 * factorial(3), so 4 * 6 = 24.
Factorial(5) returns 5 * factorial(4), so 5 * 24 = 120.