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
Related
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.
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.
Please, someone, tell me how is the result 384 here.
According to me:
Called function value is greater than 2 so, the result should be
8 * fac(8 - 2)
64-2
ans: 62
I understand something happening with "fac" please explain.
let factoria = function fac(n){
return n < 2 ? 1 : n * fac(n - 2);
}
console.log(factoria(8));
// result 384
This line n * fac(n - 2) is recursively calling the itself with new value. At first it will be called with 8 * fac(8 - 2)so now fac will be called again with 6, then again with 4 and so on
let factoria = function fac(n) {
console.log(n)
return n < 2 ? 1 : n * fac(n - 2); // recursive function
}
console.log(factoria(8));
If I put return (n-1)*n that is 8-1=7*8=56
But if I put like in the book example return factorial(n-1)*n then it returns 40320.
How does the calculation/math works? It returns a function, it return itself - right?
But I don't know how this works. How does it get to the number 40320?
const factorial = function(n) {
if (n === 0) {
return 1
} else {
return factorial(n - 1) * n
}
}
console.log(factorial(8))
We can calculate the factorial of any natural number (n) by doing:
n! = n * n-1 * n-2 * n-3 * ... * 1
Eg:
4! = 4 * 3 * 2 * 1 = 24
This can be simplified to:
n! = n * (n-1)!
Eg:
4! = 4 * (4-1)! = 4 * 3!
3! = 3 * (3-1)! = 3 * 2!
2! = 2 * (2-1)! = 2 * 1!
1! = 1 * (1-1)! = 1 * 0!
0! = 1
So solving this, we can now work back up our equations:
0! = 1
1! = 1 * 0! = 1 * (1) = 1 // <--- subbing in as we now know the result of 0! to be 1
2! = 2 * 1! = 2 * (1) = 2
3! = 3 * 2! = 3 * (2) = 6
4! = 4 * 3! = 4 * (6) = 24
When we do this with code, we can use recursion. This means we call a function within itself. Taking the above example we can do this using a function called fact() instead of using the ! notation:
fact(4) = 4 * fact(4-1) = 4 * fact(3) // same as: 4! = 4 * (4-1)! = 4 * 3!
So after running fact(4), we see that we are returning / trying to calculate the result of 4 * fact(3). But we don't know what fact(3) is yet, so we need to calculate it:
fact(3) = 3 * fact(3-1) = 3 * fact(2)
Here we are trying to calculate 3 * fact(2), but we don't know what fact(2) is yet, so we need to work it out:
fact(2) = 2 * fact(2-1) = 2 * fact(1)
Again, we need to work out what fact(1) is:
fact(1) = 1 * fact(1-1) = 1 * fact(0)
Lastly, we need to work out what fact(0) is:
fact(0) = 1
Here we get fact(0) is equal to 1. Notice how fact(0) returns a value which doesn't have a reference to another fact call. This means that we have reached our base case (defined in your if(n===0)) and can now calculate/traverse our previous equations we didn't know how to answer.
So going back up to fact(1) we now replace the call to fact(0) with 1
fact(1) = 1 * fact(0) 1 = 1
Now we know what fact(1) is, we can now calculate fact(2):
fact(2) = 2 * fact(1) 1 = 2
Now we know what fact(2) is, we can calculate fact(3):
fact(3) = 3 * fact(2) 2 = 6
Lastly, we can calculate fact(4):
fact(4) = 4 * fact(3) 6 = 24
So, using this, we get fact(4) = 24
This is the basis of how this recursive function works.
So if you use return (n-1)*n at the end of your function instead of return fact(n-1) * n you are simply just doing one return, and not calling your function again to calculate the factorial of n-1.
It returns factorial(n-1)*n instead of (n-1)*n, hence the calculation would not be just 8*7 = 56. Instead, since it is returning a call to itself, the final calculation would be 8*7*6*5*4*3*2*1 = 40320.
This is called a recursive function. When you called factorial(8), it will return factorial(7)*8, which called factorial(7) before returning. factorial(7) returns factorial(6)*7, which called factorial(6) before returning. This goes all the way until factorial(2) returns factorial(1)*1, which called factorial(1) that returns 1.
Then factorial(2) returns factorial(1)*2 = 1*2 = 2, factorial(3) returns factorial(2)*3 = 2*3 = 6, factorial(4) returns factorial(3)*4 = 6*24 = 24, and so on. Lastly, factorial(8) returns factorial(7)*8 = 5040*8 = 40320
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