Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

factorials question

def factorial(n) if n == 0 1 elsif n < 0 "NAN" elsif n*factorial(n-1) end

I think this is somewhat right. I don't understand what n*factorial(n-1) does, though. So if I were to just type factorial(4) in the command line, how does n*factorial(n-1) know to loop until it gets to 1*(1-1). Also, isn't factorial(n-1) a new variable? How does Ruby know factorial(n-1) is the same as factorial(n) - 1?

Is it doing: 4*3 3*2 2*1 1*0 then summing? What's triggering the loop?

3 Answers

Hey Lucas,

I'm not too familiar with Ruby, so I wrote this in PHP to help you explain factorials.

function factorial($n){
    if($n == 0) {
        return 1;
    } elseif($n < 0) {
        echo "NAN";
    } else {
        return $n * factorial($n-1);

    }
}

Let's call the function with a parameter of 5.

This type of function is a recursive function, meaning that you can call the function within itself. With this factorial function, you're giving it a parameter (in my case, the parameter is $n). The program then reads the first line of the function when you call it, which is the if statement. If $n equals 0, return 1 (or true). Being that $n equals 5, it skips this if block and goes to the first else if, if $n < 0. (this is here in case the parameter happens to be a negative number.) 5 isn't a negative number, so it skips to the last else if block of code. Using the parameter 5, the last block of code reads:

5 * factorial(5 - 1)

..which calls the function again (causing the loop to have a new parameter, which will now be 4). This function loops itself taking the product of $n * factorial and keeps multiplying as it loops in the last line of the function.

5 * factorial(5 - 1)  //$n is now 4
20 * factorial(4 - 1) // $n is now 3
60 * factorial(3 - 1)  // $n is now 2
120 * factorial(2 - 1) // $n is now 1
120 * factorial(1 - 1) // $n is now 0

Now that $n equals 0, when the function calls itself, the first if statement is true. So the returned product of the function is the 5 factorial ( 5! == 5*4*3*2*1).

Hope this helps. :)

Awesome, thank you so much!

So if I were to change

return $n * factorial($n-1);

to

return $n * factorial($n+1);

Would the computer know it was a recursive function and keep on spitting out new n's until it triggers an "if" clause (let's say instead of 0 I put an upper limit of 100 on it. If I don't put an upper limit, would it go to infinity?

I guess I'm just not sure how the computer knows what's a recursive function.

Like, would

return $n * factorial($n) - 1;

Not be recursive? If $n = 3, then would it just be 3*3 - 1 = 8. The end?

If you changed it to

return $n * factorial($n + 1);

it would go until you set an upper limit like you said, however, I think it reaches infinity around 170.

The reason its recursive is it keeps calling itself until it reaches a statement that causes it to not do so.
For instance, lets say we created a function called addition and set it to add numbers between 1 and 20 together.

function addition($n) {
if ($n == 20) {
return 1;
} else if ($n < 0) {
echo "NAN";
} else {
return $n + addition($n+1);  
}
}

The reason recursion happens is because your calling the "addition" function WITHIN the "addition" function. You're making it call itself until you don't want it to. Without a breakpoint/limit, it becomes an infinite loop. Technically the computer doesn't know its recursive, it's just doing what its told.

When I tried this statement:

return $n * factorial($n) - 1;

I got a this error:

Fatal error: Allowed memory size of 33554432 bytes exhausted

Fun fact: If you google the word recursion, the search page asks "Did you mean: recursion". Sometimes, google has jokes! :D

"Mind blown"

Thanks! I get it now.

Glad I can help! :)