Here is my second post, a week after the first. As said before, it is about recursion in computer science.
My first post was about using recursion to solve math problems. However, recursion is also a common method to solve programming problems. I will try to present everything in a way that is not language-specific, and I will also post code in Python and Java (the languages I am most familiar with). For Java, I will simply post the function, to run the code paste it into your own class, and call it in main.
There is one large difference between recursion in math and programming. In math, using a recursion to find a larger value works forwards, and the values calculated are increasing. In programming, a recursion works backwards.
Recursion is used in computer science to break down problems into smaller cases of the same problem. This is achieved by having a function call itself, which seems counter-intuitive at first, but turns out to be very powerful.
Recursion requires two parts:
A base case
A recursive call
The base case is a conditional statement that checks whether the recursion has reached a value that is already known. The base case is very important! Without a base case, the recursion will never end, and the program will not finish (usually resulting in a stack overflow).
The recursive call is at least one call to the same function, and is required for you to actually be implementing recursion.
This may seem confusing at first, but let us apply recursion to a simple problem.
Given a positive integer , find using recursion.
The motivation to apply recursion is that there is a simple relationship between factorials of consecutive integers: So, let us try this. To use recursion, we write a function taking one input, , that calculates factorials. It simply returns .
Python:
def factorial(n):
return n*factorial(n-1)
Java:
static int factorial(int n) {
return n*factorial(n-1);
}
Run the above code in your own environment, with an input of, say, . Does the function return , as it should? No, it doesn't. In Python, an error message says
RuntimeError: maximum recursion depth exceeded
and Java throws a
java.lang.StackOverflowError
What happened? You might notice a missing piece of the function. The recursive call is in the function, but what about the base case? Try tracing how the function runs.
Here is what the function ends up returning after 5 calls: This seems fine. Continuing, Uhhh, not looking so good anymore. In fact, this never stops, and this is why the maximum recursion depth is exceeded and the stack overflows.
Hopefully, that illustrated the horrors of forgetting the base case. Now, let us try to add the base case. What value of is the smallest possible, the one that doesn't rely on other values? Since is a positive integer, is the base case. If the input is , what should the function return? Simply . All this takes is a single if-statement.
Python:
def factorial(n):
if n==1:
return 1
return n*factorial(n-1)
Java:
static int factorial(int n) {
if (n==1) return 1;
return n*factorial(n-1);
}
Try running these functions in your own environment with an input of . They should both return the correct value, .
Okay, problem solved, on to the next problem:
A board is composed of a row of 10 squares. A token starts on the leftmost square, and has 15 moves. Each move, it can stay still or move 1 square left or right. If the token cannot move off the board, in how many ways can the token end on the 10th square after all moves are used?
To use recursion on this problem, we try to split the problem into smaller and smaller problems, until the problem becomes something like
The answer to this, is, of course, 1 if and 0 otherwise.
The initial problem can be split into these three problems:
In how many ways can a token on square end on the 10th square with 14 moves left?
In how many ways can a token on square end on the 10th square with 14 moves left?
In how many ways can a token on square end on the 10th square with 14 moves left?
Now, notice that every possible problem can be split into three parts, one to the left with one less move, one in the same square with one less move, and one to the right with one less move. This motivates creating a function that takes two parameters. We want parameters that uniquely define the problem. Think for a little about what the two parameters should be...
Okay, got it? If not, here is the answer. We want one parameter that tells us how many moves are left. We want a second parameter that tells us which square the token is on. Adding the total number of squares is also a possibility, but it is the same for every one so this is not necessary.
Now, let us write this function. First, try to write it on your own. Remember, the function should take two parameters, and it should have a base case, and a recursive call. The base case is when the problem shouldn't be split anymore: if the token fell off the board, there are 0 ways, and if there are 0 moves left, the answer is determinable. The recursive call should return the sum of all possible positions with one less move. Take a few minutes to try to write the function.
Python:
def token(moves, square):
if moves==0:
if square==10:
return 1
return 0
if square<1 or square>10:
return 0
return token(moves-1,square-1)+token(moves-1,square)+token(moves-1,square+1)
Java:
static int token(int moves, int square) {
if (moves==0) {
if (square==10) return 1;
return 0;
}
if (square<1 || square>10) return 0;
return token(moves-1,square-1)+token(moves-1,square)+token(moves-1,square+1);
}
Both of these functions return the correct answer, .
Problems:
Write a recursive program to compute the triangular numbers (the sum of the numbers from 1 to ).
Write a recursive program that makes a certain number of cents into coins (pennies, nickels, dimes, and quarters).
Congratulations on making it this far, and thanks for reading! Please tell me if this was too hard, easy, confusing, or anything like that.
Next week we will talk about recurrence relations, and the week after, probably more on recursion in computer science!
Easy Math Editor
This discussion board is a place to discuss our Daily Challenges and the math and science related to those challenges. Explanations are more than just a solution — they should explain the steps and thinking strategies that you used to obtain the solution. Comments should further the discussion of math and science.
When posting on Brilliant:
*italics*
or_italics_
**bold**
or__bold__
paragraph 1
paragraph 2
[example link](https://brilliant.org)
> This is a quote
\(
...\)
or\[
...\]
to ensure proper formatting.2 \times 3
2^{34}
a_{i-1}
\frac{2}{3}
\sqrt{2}
\sum_{i=1}^3
\sin \theta
\boxed{123}
Comments
How did you get the answer in the last example. What did you tell it to print (take the python as an example)?
Log in to reply
Oh yes good point. In python,
since there are 15 moves, and the token starts on square 1.
Log in to reply
Thanks. :) That can get confusing sometimes, depending on how you define your function. For instance, when I solved a similar problem, I counted moves up instead of down, so I needed to start at token(1,1).