Mit6 100l f22 Lec16
Mit6 100l f22 Lec16
NUMERICS
(download slides and .py files to follow along)
6.100L Lecture 16
Ana Bell
1
REVIEW OF RECURSION FROM
LAST LECTURE, WITH AN EXAMPLE
Base cases:
Females(1) = 1
Females(2) = 1
Recursive case
Females(n) = Females(n-1) + Females(n-2)
6.100L Lecture 16
FIBONACCI RECURSIVE CODE
(MULTIPLE BASE CASES)
def fib(x):
if x == 1 or x == 2:
return 1
else:
return fib(x-1) + fib(x-2)
6.100L Lecture 16
HIGH-LEVEL VIEW OF def fib(x):
FIBONACCI with if x == 1 or x == 2:
return 1
RECURSION else:
PYTHON TUTOR LINK return fib(x-1) + fib(x-2)
Fib(6)
Fib(5) Fib(4)
Fib(2) Fib(1)
6.100L Lecture 16
INEFFICIENT FIBONACCI
fib(x) = fib(x-1) + fib(x-2)
Fib(6)
Fib(5) Fib(4)
Fib(2) Fib(1)
6.100L Lecture 16
FIBONACCI WITH
MEMOIZATION
Python Tutor LINK
def fib_efficient(n, d):
if n in d:
return d[n]
else:
ans = fib_efficient(n-1, d) + fib_efficient(n-2, d)
d[n] = ans
return ans
d = {1:1, 2:1}
print(fib_efficient(6, d))
6.100L Lecture 16
EFFICIENT FIBONACCI CHECKS the DICT FIRST
n fib(n)
Fib(6) 1 1
2 1
Fib(5) Fib(4) 3 2
4 3
Fib(4) Fib(3)
5 5
6 8
Fib(3) Fib(2)
Fib(2) Fib(1)
6.100L Lecture 16
EFFICIENCY GAINS
6.100L Lecture 16
A MORE PRACTICAL EXAMPLE
WHAT ARE ALL THE WAYS YOU CAN MAKE A SCORE OF x IN BASKETBALL?
def score_count(x):
""" Returns all the ways to make a score of x by adding
1, 2, and/or 3 together. Order doesn't matter. """
if x == 1:
return 1
elif x == 2:
return 2
elif x == 3:
return 3
else:
return score_count(x-1)+score_count(x-2)+score_count(x-3)
6.100L Lecture 16
A MORE PRACTICAL EXAMPLE: PYTHON TUTOR LINK
WHAT ARE ALL THE WAYS YOU CAN MAKE A SCORE OF x IN BASKETBALL?
def score_count(x):
""" Returns all the ways to make a score of x by adding
1, 2, and/or 3 together. Order doesn't matter. """
if x == 1:
return 1
elif x == 2:
return 2
elif x == 3:
return 3
else:
return score_count(x-1)+score_count(x-2)+score_count(x-3)
Recursive step: Let future function calls do the work down until base cases
Ways to make a score of x means you could have made:
a score of (x-1) or a score of (x-2) or a score of (x-3)
If you make a score of x-1 you can just add 1 to it to make the score of x.
If you make a score of x-2 you can just add 2 to it to make the score of x.
If you make a score of x-3 you can just add 3 to it to make the score of x.
11
6.100L Lecture 16
HIGH-LEVEL VIEW def score_count(x):
if x == 1:
of score_count
return 1
elif x == 2:
return 2
elif x == 3:
return 3
else:
return score_count(x-1)+score_count(x-2)+score_count(x-3)
score(6)
score(2)
score(4) score(3)score(2) score(3) score(2)
score(3) score(1)
score(2)
12
6.100L Lecture 16
SUM of LIST ELEMENTS
13
6.100L Lecture 16
LISTS ARE NATURALLY RECURSIVE
def total_iter(L):
result = 0
for e in L:
result += e
return result
14
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
VISUALIZING LISTS as RECURSIVE
10 20 30 40 50 60
6.100L Lecture 16
SUM of LIST ELEMENTS:
the PIECES
else:
30
6.100L Lecture 16
SUM of LIST ELEMENTS:
the BASE CASE (one option)
31
6.100L Lecture 16
SUM of LIST ELEMENTS:
the BASE CASE (another option)
32
6.100L Lecture 16
SUM of LIST ELEMENTS:
the RECURSIVE STEP
33
6.100L Lecture 16
SUM of LIST ELEMENTS
RECURSIVE STEP will EVENTUALLY END
34
6.100L Lecture 16
SUM of LIST ELEMENTS:
TAKEAWAYS, Python Tutor LINK
35
6.100L Lecture 16
YOU TRY IT!
Modify the code we wrote to return the total length of all strings
inside L:
def total_len_recur(L):
if len(L) == 1:
return _______
else:
return __________________
36
6.100L Lecture 16
LOOKING for an
ELEMENT in a LIST
37
6.100L Lecture 16
ANOTHER EXAMPLE:
Is an ELEMENT in a LIST?
(careful with this implementation)
def in_list(L, e): • Let’s start by following the
if len(L) == 1: same pattern as the prev
return L[0] == e example
else: • Base case is when we have
return in_list(L[1:], e) one element
• Check if it’s the one we are
looking for
• Recursive step looks at the
remaining elements
• Grab the list from index 1
onward and look for e in it
38
6.100L Lecture 16
ANOTHER EXAMPLE:
Is an ELEMENT in a LIST?
(careful with this implementation) Python Tutor
def in_list(L, e): • Test it out
if len(L) == 1: • test = [2,5,8,1] and e=1
return L[0] == e gives True
• ok
else:
return in_list(L[1:], e)
• test = [2,1,5,8] and e=1
gives False
test = [2,5,8,1] • Not ok!
print(in_list(test, 1))
• It checks only if the last
test = [2,1,5,8]
elem is the one we are
looking for!
print(in_list(test, 1))
39
6.100L Lecture 16
ANOTHER EXAMPLE:
Is an ELEMENT in a LIST?
(fix the implementation)
def in_list(L, e): • Still want to look at
if len(L) == 1: elements one at a time
return L[0] == e • Need to check whether the
else: element we extracted is the
# Check the first element one we are looking for at
each function call
# before looking in the rest
return in_list(L[1:], e)
40
6.100L Lecture 16
ANOTHER EXAMPLE:
Is an ELEMENT in a LIST?
(fix the implementation)
def in_list(L, e): • Still want to look at
if len(L) == 1: elements one at a time
return L[0] == e • Add the check in the
else: recursive step, before
if L[0] == e: checking the rest of the list.
return True
else:
return in_list(L[1:], e)
41
6.100L Lecture 16
ANOTHER EXAMPLE:
Is an ELEMENT in a LIST?
(test the implementation) Python Tutor LINK
def in_list(L, e): • Test it now
if len(L) == 1: • test = [2,5,8,1] and e=1
return L[0] == e gives True
else: • ok
if L[0] == e: • test = [2,1,5,8] and e=1
return True gives True
else: • ok
return in_list(L[1:], e) • test = [2,5,8] and e=1 gives
False
• ok
42
6.100L Lecture 16
ANOTHER EXAMPLE:
Is an ELEMENT in a LIST?
(improve the implementation)
def in_list(L, e): • Two cases that return L[0]
if len(L) == 0: • Add case when L is empty
return False
• Simplify the code to check
elif L[0] == e: the first element as another
return True base case
else:
return in_list(L[1:], e)
43
6.100L Lecture 16
BIG IDEA
Each case (base cases, recursive step)
must return the same
type of object.
Remember that function returns build upon each other!
If the base case returns a bool and the recursive step returns
an int, this gives a type mismatch error at runtime.
44
6.100L Lecture 16
FLATTEN a LIST with
ONLY ONE LEVEL of LIST
ELEMENTS
45
6.100L Lecture 16
FLATTEN a LIST CONTAINING LISTS of ints
e.g. [[1, 2],[3, 4],[9, 8, 7]]
gives [1, 2, 3, 4, 9, 8, 7]
def flatten(L): • Base case
if len(L) == 1: • There is only one element
in L
else: • For example:
[[2,3,4]]
46
6.100L Lecture 16
FLATTEN a LIST CONTAINING LISTS of ints
e.g. [[1, 2],[3, 4],[9, 8, 7]]
gives [1, 2, 3, 4, 9, 8, 7]
def flatten(L): • Base case
if len(L) == 1: • Return that element
return L[0]
• For example:
else: [[2,3,4]]
Returns:
[2,3,4]
47
6.100L Lecture 16
FLATTEN a LIST CONTAINING LISTS of ints
e.g. [[1, 2],[3, 4],[9, 8, 7]]
gives [1, 2, 3, 4, 9, 8, 7]
def flatten(L): • Recursive step
if len(L) == 1: • Recall that + between two
return L[0] lists concatenates the
else: elements into a new list
return L[0] + #something • Make a new list containing
the first element and…
48
6.100L Lecture 16
FLATTEN a LIST CONTAINING LISTS of ints
e.g. [[1, 2],[3, 4],[9, 8, 7]]
gives [1, 2, 3, 4, 9, 8, 7]
Python Tutor LINK
def flatten(L): • Recursive step
if len(L) == 1: • … flatten the rest of the
return L[0] remaining list
else: • For example:
return L[0] + flatten(L[1:]) [[1,2],[3,4],[9,8,7]]
Returns:
[1,2] +
flatten([[3,4], [9,8,7]])
49
6.100L Lecture 16
YOU TRY IT!
Write a recursive function according to the specs below.
def in_list_of_lists(L, e):
"""
L is a list whose elements are lists containing ints.
Returns True if e is an element within the lists of L
and False otherwise.
"""
# your code here
50
6.100L Lecture 16
WHEN to USE RECURSION
51
6.100L Lecture 16
INTUITION for WHEN to use
RECURSION
Remember when we learned while loops?
Remember when we tried to write a program that kept asking
the user which way to go in the Lost Woods of Zelda?
We did not know ahead of time how many times we needed to
loop! (aka how many levels of if/else we needed)
While loops kept iterating as long as some condition held true.
© Nintendo. All rights reserved. This content is excluded from our
Creative Commons license. For more information, see
if <exit right>: https://ocw.mit.edu/help/faq-fair-use/
<set background to woods_background>
if <exit right>:
<set background to woods_background>
if <exit right>:
<set background to woods_background>
and so on and on and on...
else:
<set background to exit_background>
else:
<set background to exit_background>
else:
<set background to exit_background> 52
6.100L Lecture 16
INTUITION for WHEN to use
RECURSION
In the list recursion examples so far, we knew how many levels
we needed to iterate.
Either look at elems directly or in one level down
But lists can have elements that are lists, which can in turn
have elements that are lists, which can in turn have elements
that are lists, etc.
How can we use iteration to do these checks? It’s hard.
for i in L:
if type(i) == list:
for j in i:
if type(j) == list:
for k in j:
if type(k) == list:
# and so on and on
else:
# do what you need to do
else:
# do what you need to do
else:
# do what you need to do
53
# done with the loop over L and all its elements
6.100L Lecture 16
PROBLEMS that are NATURALLY
RECURSIVE
A file system
Order of operations in a calculator
Scooby Doo gang searching a haunted castle
Bureaucracy
54
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
1 2 3 4
55
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
2 3 4 1
56
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
2 3 4 1
57
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
3 4 2 1
58
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
3 4 2 1
59
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
4 3 2 1
60
6.100L Lecture 16
LET’S SEE HOW TO GO FROM ONE
LEVEL to MANY LEVELS (RECURSIVELY)
4 3 2 1
61
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
TOP-LEVEL ONLY
else:
62
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
TOP-LEVEL ONLY
63
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
TOP-LEVEL ONLY
64
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
TOP-LEVEL ONLY
65
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
TOP-LEVEL ONLY
Python Tutor LINK
def my_rev(L): • Test it
if len(L) == 1: test = [1, 2, "abc"]
return L # prints
['abc', 2, 1]
else:
return my_rev(L[1:]) + [L[0]] test = [1,['d'],['e',['f', 'g']]]
# prints this, notice it
# just reverses top-level elems
test = [1, 2, "abc"] [['e', ['f', 'g']], ['d'], 1]
print(my_rev(test))
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
67
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
If it’s a list,
68
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
If it’s a list,
69
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
70
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
And so on.
71
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
72
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
73
6.100L Lecture 16
ALL ELEMENTS GET REVERSED
74
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
75
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
76
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
77
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
6.100L Lecture 16
REVERSE a LIST of ELEMENTS:
ALL ELEMENTS GET REVERSED
CLEANED UP CODE
def deep_rev(L): • Extract out the empty list
if L == []: • Extract out L[0]
return []
elif type(L[0]) != list:
return deep_rev(L[1:]) + [L[0]]
else:
return deep_rev(L[1:]) + [deep_rev(L[0])]
81
6.100L Lecture 16
BIG IDEA
Recursion procedure from this
lecture can be applied to any
indexable ordered sequence.
The same idea will work on problems involving strings.
The same idea will work on problems involving tuples.
82
6.100L Lecture 16
MAJOR RECURSION TAKEAWAYS
6.100L Lecture 16
YOU TRY IT!
I added many practice recursion questions in the .py file
associated with this lecture, to prep for the quiz.
1) An exercise to implement a recursive function (no lists within
lists etc.)
2) An exercise to implement a recursive function (with lists
within lists within lists etc.)
3) Three buggy recursion implementations to fix.
84
6.100L Lecture 16
MITOpenCourseWare
https://ocw.mit.edu
For information about citing these materials or our Terms ofUse,visit: https://ocw.mit.edu/terms.
85