Can anyone explain this to me? I'm having trouble wrapping my head around this concept of having function within a function.
function factorialize(num) {
if (num === 0) {
return 1;
}
return num * factorialize(num-1);
}
factorialize(10);
This is not a loop right? Why does the function call itself continuously? How does it know when to stop? Wouldn't it just continue to factorialize negative numbers to infinity?
Appreciate the help and guidance as always.
This is not a loop right?
Nope, it is not. It is a recursive function, a function that calls itself until a certain condition is met. In this case, is when num is equals to 0.
Why does the function call itself continuously?
Because the function is called in the return value of this function. It will continue calling the function itself, until num equals 0. In which case the function will exit and return 1.
How does it know when to stop?
The condition if (num === 0). The variable num gets subtracted if num isn't equal to 0 as stated in the code return num * factorialize(num-1);. Notice that the function returns fresh function call but with the parameter num - 1. When num becomes 0. The function returns 1.
Wouldn't it just continue to factorialize negative numbers to
infinity?
Because we have this if (num === 0) condition. So the num parameter decreases each time the code return num * factorialize(num-1); gets called, and eventually the above condition gets fulfilled and the function exits.
We can break it down step by step:
factorialize(10) gets called.
num is not 10, so return num * factorialize(num - 1). In this case num is 10 and num - 1 is 9, so we are actually returning the following: 10 * factorialize(10 - 1).
factorialize(9) gets called, then repeat step (1) and (2) until you get factorialize(0).
When you reach factorialize(0), it will return 1. So the whole function effectively returns 10 * 9 * 8 * ... 1 * 1.
Makes sense?
Recursion is a technique for iterating over an operation by having a function call itself repeatedly until it arrives at a result. You can read about it here
Lets visualize:
factorialize(10)
10*factorialize(9)
9*factorialize(8)
8*factorialize(7)
7 *factorialize(6)
6 *factorialize(5)
5 *factorialize(4)
4 *factorialize(3)
3 *factorialize(2)
2 *factorialize(1)
1 *factorialize(0)
1 (if num==0 return 1)
1
2
6
24
120
720
5040
40320
362880
3628800
Hope this helps!
Each time the function "factorialize" runs your argument "num" get decremented by
1. So num will run from 10 to 1 and when 1 is returned it will reach its terminal case 0. It is only terminal because of your "if" clause ( your base case ) when num === 0, you return 1, and your recursive "factorizlize" is never reached, so it is never executed.
I am not really good with analogies. However, If it still doesn't make sense let me know.
Every iterative problem can be solved by using recursion. try to look at this code
var start = 1;
var end = 10;
var increment = 1;
document.write("loop output: ")
for(var num = start; num <= end; num = num + increment){
document.write(num);
document.write(" ");
}
document.write("\n function output:\n")
function iteration(num) {
//stop condition statement
if (num > end) {
return 1;
}
// inside code block
document.write(num);
document.write(" ");
//incremention
iteration(num+increment);
}
iteration(start);
It uses internal functional frame stack for recursion purpose. for more about recursion look here . little practice is need to understand this concept.Hope make sense. Happy Coding !
Related
Produce the sum of the first n values in an array.
function sum(arr, n) {
if (n <= 0 ){
return 0;
} else {
return sum(arr, n-1) + arr[n-1];
}
}
Hello, I have this simple recursive function from freecodecamp. I understand the concept of recursion, however I can't seem to wrap my brain around why this works in this exact use case.
I am mainly struggling to understand how the count is being increased and stored to produce a final total sum, as well as why the function doesn't return 0 as the sum once it hits its breakpoint.
Any explanations are appreciated, thank you.
Also this is not for a project or anything of the sorts, just trying to understand this concept better.
Think of each recursive call as adding a frame on the stack. All the called frames have to give answer before you can compute answer for current frame.
Caller program starts:
FRAME_A
sum([5,7,10],3)
n <= 0: False
answer here = sum([5,7,10],2) + 10
^
wait for this to be computed
let's call this WAIT_A
--------
FRAME_B
sum([5,7,10],2)
n <= 0: False
answer here = sum([5,7,10],1) + 7
^
wait for this to be computed
let's call this WAIT_B
---------
FRAME_C
sum([5,7,10],1)
n <= 0: False
answer here = sum([5,7,10],0) + 5
^
wait for this to be computed
let's call this WAIT_C
---------
FRAME_D
sum([5,7,10],0)
n <= 0: True
return 0
FRAME_D is done.
(Now, we are rolling back)
WAIT_C is now 0. FRAME_C answer is 0 + 5 = 5. FRAME_C is done.
WAIT_B is now 5. FRAME_B answer is 5 + 7 = 12. FRAME_B is done.
WAIT_A is now 12. FRAME_A answer is 12 + 10 = 22. FRAME_A is done.
All frames are done. Final answer = 22.
//This program calculates how many times a number is divisible by 2.
//This is the number and the amount of times its been split into 2.
let Num=64
let divisible=0
//This is the ternary operator, it basically asks a question.
Num % 2 === 0 ?
divisible=divisible++ : document.write(divisible);
Num/=2;
Num % 2 === 0 ?
divisible=divisible++ : document.write(divisible);
num/=2
Num % 2 === 0 ?
divisible=divisible++ : document.write(divisible);
//Once the statement evaluates to false it writes the amount of times the number has been divided
by 2 into the document.
You could try it with a loop.
let num=64;
let divisible=0;
while(num % 2 === 0) {
num /= 2;
divisible++;
}
console.log(divisible);
document.write(divisible);
There are several issues with this code. Some of the comments have pointed out the looping concerns. However, one that stands out that won't be addressed with a loop is your misuse of the post-fix increment operator, ++. This operator returns the value and then increments the value, so divisible = divisible++ will result in divisible remaining unchanged. Based on your intent, all you need to do is divisible++.
Try the following:
while(true){
if(Num % 2 === 0){
divisible++;
Num /=2;
}
else{
document.write(divisible);
break;
}
}
Here as per example given for 64 and no looping is provided , it will never go to
document.write(divisible) statement in 3 step provided above . That's why nothing getting printed .
Moreover , divisible=divisible++ doesn't make any sense . Here , since it is postfix operartor , first value will be assigned then it will be incremented so value of divisible will be 0 only .
Num % 2 === 0 ?divisible++ : document.write(divisible);
And , as per my understanding document.write accepts string parameter but here divisible is of number type .
I need to get random numbers but can't use the same number more than once.
I wrote the following functions to create a random number and to check if it has not been used yet.
function randomRecep(){
return Math.floor((Math.random() * 3));
}
function assignTemp(tempArr){
console.log("Started assign function, tempArr has: "+tempArr);
var num = randomRecep();
for (var i = 0; i < tempArr.length; i++) {
console.log("num is: " + num + ". check for doubles. tampArr["+i+"] is: "+tempArr[i]);
if (num == tempArr[i]){
console.log("FOUND DOUBLE! random num = "+num+" IS ALREADY IN array:"+tempArr)
assignTemp(tempArr);
break;
}
}
tempArr.push(num);
console.log("pushed " + num + "into array. now is:" + tempArr);
return num;
}
following is a console output. it seems that the check is working but for some reason at the end of the check instead of just pushing the unique random number and returning its value, it seems that the program pushes also all the previous duplicate numbers and returns the first random number instead of the last one that passed the check. why is that?
Started assign function, tempArr has: -1,2,1
code.js:104 num is: 1. check for doubles. tampArr[0] is: -1
code.js:104 num is: 1. check for doubles. tampArr[1] is: 2
code.js:104 num is: 1. check for doubles. tampArr[2] is: 1
code.js:106 FOUND DOUBLE! random num = 1 IS ALREADY IN array:-1,2,1
code.js:101 Started assign function, tempArr has: -1,2,1
code.js:104 num is: 1. check for doubles. tampArr[0] is: -1
code.js:104 num is: 1. check for doubles. tampArr[1] is: 2
code.js:104 num is: 1. check for doubles. tampArr[2] is: 1
code.js:106 FOUND DOUBLE! random num = 1 IS ALREADY IN array:-1,2,1
code.js:101 Started assign function, tempArr has: -1,2,1
code.js:104 num is: 0. check for doubles. tampArr[0] is: -1
code.js:104 num is: 0. check for doubles. tampArr[1] is: 2
code.js:104 num is: 0. check for doubles. tampArr[2] is: 1
code.js:113 pushed 0into array. now is:-1,2,1,0
this result is good and the idea is that it would stop here. but the process continues on:
code.js:113 pushed 1into array. now is:-1,2,1,0,1
code.js:113 pushed 1into array. now is:-1,2,1,0,1,1
I found code which is much simpler that achieves the above goal. However I am trying to learn and I don't yet understand what went wrong at the end of my method. where is the flaw in the logic?
So the problem with your current code is that you use break, where return should be used here
if (num == tempArr[i]){
console.log("FOUND DOUBLE! random num = "+num+" IS ALREADY IN array:"+tempArr)
assignTemp(tempArr);
break; // <-- should be return instead
}
The reason for this is, that once a non-unique number is found, you restart searching the next numbers, but the break will exit the loop, and directly after the for loop, you add num to your array. So, it would first add a potentially new unique number, and then exit that loop, and return to exit your first loop and then add the non-unique number ;)
You could also rewrite your code in the following way (I do not know if you have any requirements to a certain JavaScript versions, or you are only allowed to use a for loop)
function randomRecep(){
return Math.floor((Math.random() * 3));
}
function assignTemp(tempArr){
const number = randomRecep();
if (tempArr.includes( number ) ) {
console.warn( `${number} exists in [${tempArr.join(', ')}]` );
return assignTemp(tempArr);
}
console.warn( `adding ${number} to [${tempArr.join(', ')}]` );
tempArr.push( number );
return tempArr;
}
const output = [];
// shouldn't call this more than the nr of output possibilities (and the pool here has 3 options)
assignTemp( output );
assignTemp( output );
assignTemp( output );
// we will always expect 0, 1, 2 in the output in some manner
console.log( output );
Here's the relevant function (this example is taken from here):
function factorial (num) {
if (num < 0) {
return -1;
}
else if (num == 0) {
return 1;
}
var tmp = num;
while (num-- > 2) {
tmp = tmp * num;
}
return tmp;
}
console.log(factorial(8));
----> 40320
As I was studying how this function works (and got stumped on the operator precedence in the expression (num-- > 2); kudos to my mentor Edwin Calte at MakerSquare for pointing that out), I noticed that the num variable decrements even though this decrementation is something that is stipulated as a precondition for the loop body to be executed and is not itself part of the loop body. I could understand why it would do that if the expression read instead like:
while (num-- > 2) {
num--;
...}
In the above example, that second num-- isn't necessary for it to work. Another similar expression where this doesn't seem to happen when I run it in my devtools console is:
if (x - 2 == 5) { x-- }
Here, it seems that if x is 7 then x will decrement by 1, not that if x is 7 then 2 will be subtracted from x, and then x will decrement by 1. But in the above example with num, the latter principle is what takes effect.
Could someone please explain why?
Because every time the expression num-- is evaluated (which it is on every iteration of the loop to see if the condition is met) it is decreasing num by one. A lot of JavaScript gurus will tell you to avoid num--, num++, --num, ++num exactly because of their not-so-intuitive side effects.
My advice would be to stick with things that are more readable at first glance, even if it is a few more characters to type.
while (num > 2) {
num = num - 1;
}
At the very least, only use them as standalone statements to make what they are doing clear.
while (num > 2) {
num--;
}
In your second example with the expression x - 2 == 5, this expression does not operate on x at all; it doesn't change it's value. You're not assigning anything back to x like you are when you do x--. x--; is exactly equivalent to x = x - 1;. It just so happens that it also returns the value of x before the assignment is made; this way it can be used as the conditional. It's like reading from a variable and then writing to it all in one statement.
num-- does two things: it subtracts 1 from the variable num (assigning the result back to num) and also returns the original value of the num to be used in the rest of the enumpression. So
(num-- > 2)
is short for:
(temp = num; num = num - 1; temp > 2)
Your while loop could be written as:
while (num > 2) {
num--;
tmp = tmp * num;
}
Notice that I no longer have num-- in the while clause. If I did, the variable would get decremented twice: once while testing the condition, and again inside the loop.
x - 2 would express a new value, ie if you opened the console and typed x - 2 it would respond with 5, but that value is not assigned to anything (and thus x is unaffected). The -- and ++ operators are self-contained statements which affect the variable on which they are operating. So your num-- > 2 is the name as saying num > 2 followed by a num = num - 1, which compares the current value, then performs a mathematical operation and assigns the result of that operation to the variable.
I understand that "a" solution is:
function Factorial(number)
{
if(number == 0 || number == 1){
return 1;
}
return number * Factorial(number -1);
}
I want to understand what exactly is going on. I understand what is going on all the way to the last part when number == 1.
If we were to take a simple example of say 3!
3 is not equal to 0 or 1 so we return 3 * Factorial(2)
2 is not equal to 0 or 1 so we return 2 * Factorial(1)
1 is equal to 1 so we return 1
How do we know when to stop? Is it the fact that we return 1 that tells the function to stop?
If that is the case, why does the function not stop when we first return 3 * Factorial(2)? Is it because it's returning a function so that it must continue until it no longer returns a function?
Thank you
I think you have to understand the logic of factorial.
So factorial is just products, indicated by an exclamation mark ie, if you write
0! = 1
1! = 1
2! = 2*1
3! = 3*2*1
4! = 4*3*2*1
5! = 5*4*3*2*1
Hope you find the pattern, so you can write the above factorials as:
0! = 1
1! = 1
2! = 2*1!
3! = 3*2!
4! = 4*3!
5! = 5*4!
So in your function you are using the similar logic.
Now in your function
if(number == 0 || number == 1)
{
return 1;
}
The above logic is to cover the first two cases i.e, 0! and 1! And
return number * Factorial(number -1);
is for the rest of the numbers.
So you are using the recursive technique of solving the factorial problem.
To understand recursion, lets take a number say 5 i.e., we want find the value of 5!.
Then first your function will check
if(number == 0 || number == 1)
which is not satisfied, then it moves to the next line ie,
return number * Factorial(number -1);
which gives
5*Factorial(5-1) which is equal to 5*Factorial(4)
Now on subsequent calls to your Factorial function it will return the value like below:
5*(4*Factorial(4-1)) which is equal to 5*(4*Factorial(3))
5*(4*(3*Factorial(3-1)) which is equal to 5*(4*(3*Factorial(2)))
5*(4*(3*(2*Factorial(2-1)))) which is equal to 5*(4*(3*(2*Factorial(1))))
Now when it returns factorial(1) then your condition
if(number == 0 || number == 1)
is satisfied and hence you get the result as:
5*4*3*2*1 = 120
On a side note:
Beware that factrial is used only for positive integers.
Recursion relies on what is called a base case:
if(number == 0 || number == 1){
return 1;
}
That if statement is called your base case. The base case defines when the recursion should stop. Note how you are returning 1 not returning the result of a call to the function again such as Factorial(number -1)
If the conditions for your base case are not met (i.e. if number is NOT 1 or 0) then you proceed to call the function again with number * Factorial(number - 1)
If that is the case, why does the function not stop when we first return 3 * Factorial(2)?
Your simple example of 3! can be elaborated like this :
return 3 * Factorial(2)
will then be replaced by
return 3 * (2 * Factorial(1))
which then will be replaced by
return 3 * (2 * 1) // = 6 Hence 6 is returned at last and recursion ends.
How do we know when to stop?
When all your Factorial(value) is replaced by a returned value we stop.
Is it the fact that we return 1 that tells the function to stop?
In a way, yes. Because it is the last returned value.
It is called recursion.
This function is called like this
var result = Factorial(3);
in Factorial function
First time
return 3*Factorial(2);
Now here return statement doesnt get executed insted Factorial is called again..
so second time
return 2*Factorial(1);
again in Factorial(1)
Third time
return 1;
So go to second
return 2*1;
Next to first
return 3*(2*1);
Finally
var result = 3*2*1 = 6.
The function is recursing (calling itself) - and taking one from "number" each time.
Eventually (as long as its a positive integer you call it with, otherwise you'll probably get an infinite loop) you'll always hit the condition (number == 1) so instead of recursing further, it'll return 1 rather than call the function again.
Then, once you have hit the bottom (1), it'll start to run the function and work back up the other way along the function call stack, using the previous result each time:
1 = 1
(2*1) = 2
(3*2) = 6
(4*6) = 24
etc
So the final return statement from the function will return the required result