In this ICS4U Grade 12 Computer Science lesson you will be learning how to
You are used to programming and solving problems using control structures such as if-else statements (selection structures) and iterative loops (repetition structures)
Another control mechanism that can be used in problem solving and programming is recursion
The basic idea behind recursion is this:
Generally when a problem can be defined in terms of itself then it can be solved recursively
The total number of pins in a triangular arrangement is called a triangle number.
You can expand that pattern by keep adding rows with more pins
There is a pattern here:
Mathematically you can write out the # of pins in the Nth row as
Triangle (N) = N + Triangle (N – 1)
Triangle(3)
Triangle (7)
Because you have defined the Nth Triangle number in terms of itself, this is a perfect problem to solve recursively.
Notice that in both examples above the sequence of additions ended with Triangle(1) = 1. This is called the base case for the problem
def triangle(N):
#Base Case
if N == 1:
return 1
#Recursive Call
else:
return N + triangle(N-1)
Notice that the Tell Tale Sign of a Recursive Function call in programming is that you define a function that calls itself
Write a main program for the Triangle Function defined above and test to see if you are getting the correct results
Go to the following website and watch how the function works its way through until the base case is hit and the recursion stops.
def triangle(N):
if N == 1:
return 1
else:
return N + triangle(N-1)
def main():
num = int(input("Calculate Triangle Number for N = "))
tNumber = triangle(num)
print("Triangle(",num,") = ", tNumber)
main()
You have probably studied and are familiar with the Fibonacci Sequence of numbers
1,1,2,3,5,8,13,,21,34,55,….
Each value in the sequence is found by adding the previous two values in the sequence.
Mathematically we can define this as
Fib (N) = Fib(N-1) + Fib(N-2) for N >= 3
The base cases for this recursion are Fib(1) = 1 and Fib(2) = 1
Translating that into a python function would look as follows
def fib(N):
if N == 1 or N == 2:
return 1
else:
return fib(N-1) + fib(N-2)
Look at the following recursive activation diagram for trying to find the 5th Fibonacci number
You might be wondering, why recursion is necessary at all, when the two programs above could have easily been written with a loop.
If you look at the pattern that occurs for the Nth triangle number, you will see that its value is just the sum of the numbers from 1 to 10
That is easily accomplished using a simple loop
def triangle(N):
sum = 0
for i in range(1,N):
sum = sum + i
return sum
This one might be a little more complicated to understand from a looping perspective, but just need to keep track of the previous two values in some variables.
def fib(N):
f1 = 1
f2 = 1
for i in range(1,N-1):
nextValue = f1 + f2
f1 = f2
f2 = nextValue
return f2
Well, the answer to the above question of recursion vs iteration, isn’t exactly straight forward.
Generally Speaking
Run the Following Code to compare the execution times for the iterative vs the recursive Triangle Number Algorithms
import timeit
def triangleRecursive(N):
if N == 1:
return 1
else:
return N + triangleRecursive(N-1)
def triangleIterative(N):
sum = 0
for i in range(1,N+1):
sum = sum + i
return sum
def main():
num = int(input("Calculate Triangle Number for N = "))
print("\nRecursive:")
start = timeit.default_timer()
tNumber = triangleRecursive(num)
end = timeit.default_timer()
elapsedNS = round((end - start)*10**9)
print("Triangle(",num,") = ", tNumber)
print("Solution took",elapsedNS,"nanoseconds\n")
print("Iterative:")
start = timeit.default_timer()
tNumber = triangleIterative(num)
end = timeit.default_timer()
elapsedNS = round((end - start) * 10 ** 9)
print("Triangle(", num, ") = ", tNumber)
print("Solution took",elapsedNS,"nanoseconds")
main()
Run the Following Code to compare the execution times for the iterative vs the recursive Fibonacci Number Algorithms
import timeit
def fibRecursive(N):
if N == 1 or N == 2:
return 1
else:
return fibRecursive(N-1) + fibRecursive(N-2)
def fibIterative(N):
f1 = 1
f2 = 1
for i in range(1,N-1):
nextValue = f1 + f2
f1 = f2
f2 = nextValue
return f2
def main():
num = int(input("Calculate the Fibonacci Number for N = "))
print("\nRecursive:")
start = timeit.default_timer()
fNumber = fibRecursive(num)
end = timeit.default_timer()
elapsedNS = round((end - start)*10**9)
print("Fibonacci(",num,") = ", fNumber)
print("Solution took",elapsedNS,"nanoseconds\n")
print("Iterative:")
start = timeit.default_timer()
fNumber = fibIterative(num)
end = timeit.default_timer()
elapsedNS = round((end - start) * 10 ** 9)
print("Fibonacci(", num, ") = ", fNumber)
print("Solution took",elapsedNS,"nanoseconds")
main()
You will learn in the next unit about a data structure called a Stack, but when python makes function calls, that structure is used to store the set of new local variables and parameters each time the function is called. There is only so much space that is available on that stack, and as we have seen, the amount of function calls that a recursive solution can make can become very high.
In the previous learning activity you probably noticed that you were getting a Recursion Depth Exceeded error. This is a stack overflow error where there are too many functions calls and the stack wouldn’t have enough space to handle that many.
The greatest common divisor (GCD) algorithm is another common algorithm that can be written both recursively and iteratively. It finds the largest factor that exists between 2 numbers (a,b)
You can see the simplicity of the recursive code vs the iterative version
def gcd(a,b):
if a == 0:
return b
else:
return gcd(b % a , a)
def gcd(a, b):
# Largest divisor 1 -> if no other ones found
g = 1
# start search for divisors at the smallest number
if a > b:
start = b
else:
start = a
# Count backwards to find the largest divisor
for i in range(start, 1, -1):
# Found largest divisor so stop
if a % i == 0 and b % i == 0:
g = i
break
return g
The Towers of Hanoi Problem is a traditional mathematical problem that can be solved using recursion. Watch the video and see if you can understand the algorithm. The code it gives is not in Python, but see if you can simulate this puzzle yourself in Python if you have time, but I’m more concerned with you just getting familiar on how this could be solved recursively
Here is an example of a recursive function that counts up by 3 for N number of times.
def count3(N):
if N == 0:
return 0
else:
return 3 + count3(N-1)
def main():
#Counts up by 3 5 times, so prints 15
print(count3(5))
#Counts up by 3 20 times, so prints 60
print(count3(20))
main()
The recursion is acting like a loop in this case, executing N number of times and adding 3 each time the recursive function is called
Try to code the following questions using an IDE of your choice. You will save those files on your computer for future reference.
Each question has:
Try your best to solve the problems yourself without looking at the solutions.
Make sure you test your programs with multiple different inputs to ensure it is functioning properly.
Treat these questions like Math homework (Do as many as you feel you need to do to feel comfortable with the material)
Name Your File: “ICS4Ufactorial.py”
Write a recursive solution to calculating a factorial. The factorial of a number N is the product of all the numbers from 1 to N. Mathematically a factorial is written as N!
This definition is recursive because the Nth factorial is N multiplied by the N-1 factorial
def factorial(N):
if N == 0:
return 1
else:
return N * factorial(N-1)
Name Your File: “ICS4Usquared.py”
In this question you are going to write a recursive function for implementing the Square of a Number 𝑁2.
An interesting way to compute the square of a number is to use the fact that
which would mean that
def squared(N):
if N == 1:
return 1
else:
return squared(N-1) + 2 * N - 1
Name Your File: “ICS4UpyramidalNumbers.py”
Let’s take a look at a tetrahedron made up of tennis balls.
The Nth pyramidal number is the total number of balls in a pyramid that has a base side length of N tennis balls
You can solve this problem by adding up the number of balls in each layer (which just happen to be the Triangle Numbers from the lesson)
Notice that the Nth pyramidal number is just the Nth Triangle Number plus the pervious Pyramidal Number
Write a recursive function to find Pyramidal Number and draw the activation diagrams showing the recursive calls for N = 3
def triangle(N):
if N == 1:
return 1
else:
return N + triangle(N-1)
def pyramidal(N):
if N == 1:
return 1
else:
return pyramidal(N-1) + triangle(N)
def main():
num = int(input("Enter N: "))
print(pyramidal(num))
main()
Name Your File: “ICS4UsumOfList.py”
It is possible to write an algorithm that finds the sum of the values inside a list using recursion as well
The base case is when the index is equal the length of theList and the recursive function should return 0
Write the function to implement this sum recursively
Draw the activation diagram showing the recursive calls for the following list
def sumList(theList,index):
if index == len(theList):
return 0
else:
return theList[index] + sumList(theList, index + 1)
def main():
x = [1,2,3,4,5]
print(sumList(x,0))
x = [4,3,7,12,17,20,22]
print(sumList(x, 0))
main()
Return to ICS4U Main Page