Previous Lecture | Lecture 15 | Next Lecture |
Lecture 15, Thu 09/05
Recursion
# CS8, 9-5-19
# Recursion
'''
- When a function contains a call to itself
- We're mostly familiar with writing code in an iterative fashion
(i.e. one statement after the other)
- Several programming languages exist where it's purely based
on recursion
- Recursive solutions are useful when the result is dependent
on the result of sub-parts of the problem
PROPERTIES OF RECURSION
- One or more base cases that provides the "stopping" (base case)
condition
- One or more recursive calls, where the parameters are "closer" to
the base case ("stopping condition")
'''
'''
Example: Factorials
N! = N * (N-1) * (N-2) * ... * 3 * 2 * 1
N! = N * (N-1)!
'''
def factorial(n):
if n == 0: # base case
return 1
return n * factorial(n-1)
assert factorial(0) == 1
assert factorial(1) == 1
assert factorial(2) == 2
assert factorial(3) == 6
assert factorial(4) == 24
# What happens if we forget the base case?
def factorial2(n):
# print(n)
return n * factorial2(n-1)
'''
Infinite recursion! No stopping condition means the functions never
returns the value
'''
# What happens if we never progress to the base case?
def factorial3(n):
if n == 0:
return 1
print(n)
return n * factorial3(n)
#factorial3(4) == 24
'''
Infinite recursion! the stopping condition is never reached!
'''
# Example: Check if a string is a palindrome
''' A palindrome is a string that is spelled the same forwards and
backwards
Examples of palindromes: racecar, hannah, civic, a, "" '''
def isPalindrome(s):
''' Returns true if s is a palindrome, returns false otherwise '''
if len(s) == 0 or len(s) == 1:
return True
if s[0] != s[-1]:
return False
return isPalindrome(s[1:len(s)-1]) # s[1:-1] also works
assert isPalindrome("racecar") == True
assert isPalindrome("civic") == True
assert isPalindrome("CS8") == False
# Example: Filter through and return a collection
''' Assuming we have a list of numbers, return a list where all even
numbers are removed '''
def removeEvenNumbers(L):
''' For a list of numbers, L, returns a list where all even numbers
are removed'''
if len(L) == 0: # base case
return []
if L[0] % 2 == 0: # case where 1st element is even
return removeEvenNumbers(L[1:])
else:
return [L[0]] + removeEvenNumbers(L[1:])
assert removeEvenNumbers([1,2,3,4]) == [1,3]
assert removeEvenNumbers([1,1,1,1]) == [1,1,1,1]
assert removeEvenNumbers([2,4,6]) == []
# Example: Fibonnaci
''' A fibonnaci sequence is the nth number in the sequence such that
it is the sum of the previous two numbers in the sequence '''
'''
f(n) = f(n-1) + f(n-2)
f(0) = 0, f(1) = 1
f(2) = f(1) + f(0) = 1
f(3) = f(2) + f(1) = 2
f(4) = f(3) + f(2) = 3
f(5) = f(4) + f(3) = 5
...
'''
def fibonnaci(n):
if n == 0:
return 0
if n == 1:
return 1
return fibonnaci(n-1) + fibonnaci(n-2)
assert fibonnaci(0) == 0
assert fibonnaci(1) == 1
assert fibonnaci(2) == 1
assert fibonnaci(3) == 2
assert fibonnaci(4) == 3
assert fibonnaci(5) == 5
assert fibonnaci(6) == 8
# Example: Reverse a string using recursion
def reverseString(s):
''' We want to return a string that is in reverse order of s
"CS8"->"8SC" '''
if s == "":
return ""
return reverseString(s[1:]) + s[0]
assert reverseString("CS8") == "8SC"
assert reverseString("") == ""
assert reverseString("a") == "a"
assert reverseString("hooray!") == "!yarooh"