To find the value to the following expression ${2^n}$ for non-negative integers ${n}$, we can use an old friend for
loop.
def exponentiate(base, exponent):
total = 1
for i in range(exponent):
total *= base
return total
print(exponentiate(2, 5))
32
But we can also use recursion to help find the value for the same expression. When solving a problem in programming, often times, multiple solutions to the same problem exist.
def exponentiate_recur(base, exponent):
if exponent == 0: #base case
return 1
return exponentiate_recur(base, exponent-1) * base
# try on your own
print(exponentiate_recur(2, 5) == 32) # this should print out True
True
The base case returns the answer to the smallest version of the problem.
For our example, the smallest version of the problem would be finding the answer to ${2^0}$.
if exponent == 0:
return 1
The recursion step solves smaller version of the problem and combines answers at each step of the smaller problem to return the final answer.
For our example, knowing the answer to ${2^4}$ would help find the answer to ${2^5}$, knowing the answer to ${2^3}$ would help find the answer to ${2^4}$, ...
small_answer = exponentiate_recur(base, exponent - 1)
return 2 * small_answer
exponentiate_recur(2, 5)
=> recursion step =>
2 * exponentiate_recur(2,4)
=> recursion step =>
2 * 2 * exponentiate_recur(2,3)
=> recursion step =>
2 * 2 * 2 * exponentiate_recur(2,2)
=> recursion step =>
2 * 2 * 2 * 2 * exponentiate_recur(2,1)
=> recursion step =>
2 * 2 * 2 * 2 * 2 * exponentiate_recur(2,0)
=> base case =>
2 * 2 * 2 * 2 * 2 * 1
=> recursion step (to combine answers) =>
32
def exponentiate_with_print(base, exponent):
if exponent == 0:
print("Current exponent is: "+ str(exponent)+ ", returning 1")
return 1
print("Current exponent is: "+ str(exponent)+ ", returning " + str(base) + " * " + "exponentiate_with_print("+ str(base) + ", " + str(exponent - 1) + ")")
return base * exponentiate_with_print(base, exponent - 1)
exponentiate_with_print(2, 5)
# What does this second function do?
def mystery2(a, b):
if b == 0:
return 0
return a + mystery2(a, b - 1)
# what is the output of the line of code below?
mystery2(5, 4)
The following sequence of numbers is called the Fibonacci numbers:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
Can you see the pattern in this sequence?
The Fibonacci numbers are defined as follows:
F(0) = 0
F(1) = 1
F(n) = F(n - 1) + F(n - 2), for n >= 2
We can expand this out a bit to see the first few Fibonacci numbers in the sequence:
F(0) = 0, by definition, (0-th Fibonacci number)
F(1) = 1, by definition, (1-st Fibonacci number)
F(2) = F(1) + F(0) = 1 + 0 = 1, (2-nd Fibonacci number)
F(3) = F(2) + F(1) = 1 + 1 = 2, (3-rd Fibonacci number)
F(4) = F(3) + F(2) = 2 + 1 = 3, (4-th Fibonacci number)
...
This sequence appears in algorithms, math, and in nature in various places. Today, we can use the definition of Fibonacci numbers to program a function that returns the n-th Fibonacci number!
Let us define a function fib(n)
that takes a non-negative integer ${n}$ as an input and outputs the $n^{th}$ Fibonacci number.
def fib(n):
# implementation of fib using for loop:
def fib(n):
fib_i_prev_prev = 0 # initialized to F(0)
fib_i_prev = 1 # initialized to F(1)
for i in range(n - 1):
# compute the next number in the sequence
fib_i = fib_i_prev_prev + fib_i_prev
# save state to use for the next computation
fib_i_prev_prev = fib_i_prev
fib_i_prev = fib_i
return fib_i
fib(4)
3
Try, on your own, writing what a recursive method for finding the n-th Fibonacci number might look like
# implementation of fib using recursion:
def fib(n):
# base case:
# ?
# recursion step:
# ?
fib(4)
While recursion solutions can be more difficult to think about at first, they can be simpler and more elegant solutions to a problem.
In lab, you have encountered the questions in which you try to figure out if a string is a palindrome. The method using a for loop looks like the following:
def is_palindrome_loop(str):
for x in range(len(str)//2):
if str[x] != str[-(x+1)]:
return False
return True
is_palindrome_loop('himalayalamih')
def is_palindrome(str):
if len(str) == 0 or len(str) == 1:
return True
if str[0] != str[-1]:
return False
else:
return is_palindrome(str[1:-1])
is_palindrome('himalayalamih')