Recursion
The factorial function is defined for all positive integers, along with . What value should have? It's the product of all integers greater than or equal to and less than or equal to . But there are no such integers. Therefore, we define 0! to equal the identity for multiplication, which is . (Defining meshes nicely with the formula for choosing things out of nnn things. Suppose that we want to know how many ways there are to choose things out of nnnthings. That's easy, because there is only one way: choose all nnn things. So now we know that, using our formula, should equal . But is , so now we know that should equal . If we cancel out the n!n!in both the numerator and denominator, we see that should equal , and it does because equals .)
So now we have a way to think about . It equals when and it equals when is positive.
var factorial = function(n) {
var result = 1;
for (var i = 1; i <= n; i++) {
result *= i;
}
return result;
};
println("The value of 5! should be " + 5*4*3*2*1);
println("The value of 5! is " + factorial(5));
println("The value of 0! should be 1");
println("The value of 0! is " + factorial(0));
Program.assertEqual(factorial(5), 120);
Program.assertEqual(factorial(0), 1);
Here is the basic idea behind recursive algorithms:
To solve a problem, solve a subproblem that is a smaller instance of the same problem, and then use the solution to that smaller instance to solve the original problem.
var factorial = function(n) {
// base case:
if (n === 0) {
return 1;
}
// recursive case:
return factorial(n-1) * n;
};
println("The value of 0! is " + factorial(0) + ".");
println("The value of 5! is " + factorial(5) + ".");
Program.assertEqual(factorial(0), 1);
Program.assertEqual(factorial(5), 120);
We can distill the idea of recursion into two simple rules:
Each recursive call should be on a smaller instance of the same problem, that is, a smaller subproblem.
The recursive calls must eventually reach a base case, which is solved without further recursion.
Challenge: is a string a palindrome?
// Returns the first character of the string str
var firstCharacter = function(str) {
return str.slice(0, 1);
};
// Returns the last character of a string str
var lastCharacter = function(str) {
return str.slice(-1);
};
// Returns the string that results from removing the first
// and last characters from str
var middleCharacters = function(str) {
return str.slice(1, -1);
};
var isPalindrome = function(str) {
// base case #1
if (str.length <= 1){
return true;
}
// base case #2
if (firstCharacter(str) === lastCharacter(str)){
return true;
} else {
return false;
}
// recursive case
return isPalindrome(middleCharacters(str));
};
var checkPalindrome = function(str) {
println("Is this word a palindrome? " + str);
println(isPalindrome(str));
};
checkPalindrome("a");
Program.assertEqual(isPalindrome("a"), true);
checkPalindrome("motor");
Program.assertEqual(isPalindrome("motor"), false);
checkPalindrome("rotor");
Program.assertEqual(isPalindrome("rotor"), true);
checkPalindrome("moon");
Recursive algorithm for computing :
The base case is when and .
If is positive and even, recursively compute , and then . Notice that you can get away with making just one recursive call in this case, computing just once, and then you multiply the result of this recursive call by itself.
If is positive and odd, recursively compute , so that the exponent either is or is positive and even. Then, .
If is negative, recursively compute , so that the exponent becomes positive. Then, .
var isEven = function(n) {
return n % 2 === 0;
};
var isOdd = function(n) {
return !isEven(n);
};
var power = function(x, n) {
println("Computing " + x + " raised to power " + n + ".");
// base case
if (n === 0){
return 1;
}
// recursive case: n is odd
if (isOdd(n)){
return power(x, n-1) * x;
}
// recursive case: n is even
if (isEven(n)) {
var y = power(x, n/2);
return y*y;
}
// recursive case: n is negative
if (n < 0) {
return 1 / power(x, -n);r
}
};
var displayPower = function(x, n) {
println(x + " to the " + n + " is " + power(x, n));
};
displayPower(3, 0);
Program.assertEqual(power(3, 0), 1);
displayPower(3, 1);
Program.assertEqual(power(3, 1), 3);
displayPower(3, 2);
Program.assertEqual(power(3, 2), 9);
displayPower(3, -1);
Program.assertEqual(power(3, -1), 1/3);
Last updated