Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Lecture 11
Recursion
Announcements for Today
Reading
Assignments
• Read 5.8 – 5.10
• Assignment 2 Graded
§ Pick up in Office Hours
§ Or from the consultants
§ Mean 22, Median 23 (A-/B+)
• Prelim, Oct 4th 7:30-9:00
§ Material up to lists
§ Review Sunday 1-3pm
§ Room TBA
• Work on Assignment 3
• Conflict with Prelim time?
§ Submit to Prelim 1 Conflict
assignment on CMS
§ LAST DAY TO SUBMIT
9/25/12
Recursion
§
§
§
§
Part 1 due Oct. 1 (pass/fail)
Consultants available Fri
Could not get any for Sat
Double shifts Sunday
2
Recursion
• Recursive Definition: A definition that is defined in terms of itself
• Recursive Function: A function that calls itself (directly or indirectly)
• Recursion: If you get the point, stop;
otherwise, see Recursion
• Infinite Recursion: See Infinite Recursion
9/25/12
Recursion
3
A Mathematical Example: Factorial
• Non-recursive definition:
n! = n × n-1 × … × 2 × 1 = n (n-1 × … × 2 × 1)
• Recursive definition:
n! = n (n-1)!
for n ≥ 0
0! = 1
Recursive case
Base case
What happens if there is no base case?
9/25/12
Recursion
4
Example: Fibonnaci Sequence
• Sequence of numbers: 1, 1, 2, 3, 5, 8, 13, ...
a0 a1 a2 a3 a4 a5 a6
§ Get the next number by adding previous two
§ What is a8?
A: a8 = 21
B: a8 = 29
C: a8 = 34
D: None of these.
9/25/12
Recursion
5
Example: Fibonnaci Sequence
• Sequence of numbers: 1, 1, 2, 3, 5, 8, 13, ...
a0 a1 a2 a3 a4 a5 a6
§ Get the next number by adding previous two
§ What is a8?
• Recursive definition:
§ an = an-1 + an-2
§ a0 = 1 § a1 = 1 Recursive
Case
Base Case
(another) Base Case
Why did we need two base cases this time?
9/25/12
Recursion
6
Fibonacci as a Recursive Function
def fibonacci(n):
"""Returns: Fibonacci no. an
Precondition: n ≥ 0 an int"""
if n <= 1:
Base case(s)
return 1
return (fibonacci(n-1)+
fibonacci(n-2)) Recursive case
What happens if we forget the base cases?
9/25/12
Recursion
7
Fibonacci as a Recursive Function
def fibonacci(n):
"""Returns: Fibonacci no. an
• Function that calls itself
Precondition: n ≥ 0 an int"""
if n <= 1:
return 1
return (fibonacci(n-1)+
fibonacci(n-2))
§ Each call is new frame
§ Frames require memory
§ ∞ calls = ∞ memory
fibonacci
n
fibonacci
n
9/25/12
Recursion
4
1
3
5
fibonacci
n
1
3
8
Fibonacci: # of Frames vs. # of Calls
• Fibonacci is very inefficient.
§ fib(n) has a stack that is always ≤ n
§ But fib(n) makes a lot of redundant calls
fib(5)
Blue line = call stack
fib(4)
fib(3)
fib(2)
fib(1)
9/25/12
fib(1)
fib(0)
fib(3)
fib(2)
fib(1)
fib(0)
Recursion
fib(2)
fib(1)
fib(1)
fib(0)
9
Recursion as a Programming Tool
• Later we will see iteration (loops)
• But recursion is often a good alternative
§ Particularly over sequences (lists, strings)
• Some languages only have recursion
§ “Functional languages”; topic of CS 3110
A4: Recursion to draw fractal shapes
9/25/12
Recursion
10
String: Two Recursive Examples
def length(s):
def num_es(s):
"""Returns: # chars in s"""
"""Returns: # of ‘e’s in s"""
# {s is empty}
# {s is empty}
if s == '':
if s == '':
return 0
return 0
# { s at least one char }
# { s at least one char }
return 1 + length(s[1:])
return ((1 if s[0] == 'e' else 0) + Imagine len(s)
num_es(s[1:]))
does not exist
9/25/12
Recursion
11
Two Major Issues with Recursion
• How are recursive calls executed?
§ We saw this with the Fibonacci example
§ Use the call frame model of execution
• How do we understand a recursive function
(and how do we create one)?
§ You cannot trace the program flow to understand
what a recursive function does – too complicated
§ You need to rely on the function specification
9/25/12
Recursion
12
How to Think About Recursive Functions
1. Have a precise function specification.
2. Base case(s): § When the parameter values are as small as possible § When the answer is determined with little calculation.
3. Recursive case(s): § Recursive calls are used. § Verify recursive cases with the specification
4. Termination: § Arguments of calls must somehow get “smaller” § Each recursive call must get closer to a base case
9/25/12
Recursion
13
Understanding the String Example
def num_es(s):
"""Returns: # of ‘e’s in s"""
# {s is empty}
if s == '':
Base case
return 0
# { s at least one char }
return ((1 if s[0] == 'e' else 0) #
+ num_es(s[1:]))
• Break problem into parts
number of e’s in s = number of e’s in s[0]
+ number of e’s in s[1:]
• Solve small part directly
Recursive case
0
1
number of e’s in s = (1 if s[0] == 'e' else 0)
+ number of e’s in s[1:]
len(s)
s H ello World!
9/25/12
Recursion
14
Understanding the String Example
• Step 1: Have a precise specification
def num_es(s):
"""Returns: # of ‘e’s in s"""
# {s is empty}
if s == '':
Base case
return 0
“Write” your return
statement using the
specification
# { s at least one char }
# return # of ‘e’s in s[0]+# of ‘e’s in s[1:]
return (1 if s[0] == 'e' else 0) + num_es(s[1:])
Recursive case
• Step 2: Check the base case
§ When s is the empty string, 0 is returned.
§ So the base case is handled correctly.
9/25/12
Recursion
15
Understanding the String Example
• Step 3: Recursive calls make progress toward termination
def num_es(s):
parameter s
"""Returns: # of ‘e’s in s"""
# {s is empty}
if s == '':
return 0
argument s[1:] is smaller than
parameter s, so there is progress
toward reaching base case 0
# { s at least one char }
argument s[1:]
# return # of ‘e’s in s[0]+# of ‘e’s in s[1:]
return (1 if s[0] == 'e' else 0) + num_es(s[1:])
• Step 4: Recursive case is correct
§ Just check the specification
9/25/12
Recursion
16
Exercise: Remove Blanks from a String
1. Have a precise specification
def deblank(s):#
"""Returns: s but with its blanks removed"""
2. Base Case: the smallest String s is ''.
if s == '':#
return s
3. Other Cases: String s has at least 1 character.
return (s[0] with blanks removed) + (s[1:] with blanks removed)
('' if s[0] == ' ' else s[0])
9/25/12
Recursion
17
What the Recursion Does
deblank
a
b
c
a
b
c
✗
deblank
a
b
c
a
b
c
b
c
a
b
c
deblank
b
c
b
c
c
b
c
deblank
c
c
a
✗
b
✗
9/25/12
c
deblank
deblank
Recursion
c
18
Exercise: Remove Blanks from a String
def deblank(s):
"""Returns: s with blanks removed"""
if s == '':
return s
# s is not empty
if s[0] is a blank:
return s[1:] with blanks removed
# s not empty and s[0] not blank
return (s[0] + #
s[1:] with blanks removed)
• Sometimes easier to break up the recursive case
§ Particularly om small part
§ Write recursive case as a
sequence of if-statements
• Write code in pseudocode
§ Mixture of English and code
§ Similar to top-down design
• Stuff in red looks like the
function specification!
9/25/12
Recursion
§ But on a smaller string
§ Replace with deblank(s[1:])
19
Exercise: Remove Blanks from a String
def deblank(s):
"""Returns: s with blanks removed"""
if s == '':
return s
# s is not empty
if s[0] in string.whitespace:
return deblank(s[1:])
# s not empty and s[0] not blank
return (s[0] +#
deblank(s[1:]))
9/25/12
• Check the four points:
Recursion
1. Precise specification?
2. Base case: correct?
3. Recursive case: progress
toward termination?
4. Recursive case: correct?
Expression: x in thelist
returns True if x is a
member of list thelist
(and False if it is not)
20
Next Time: A Lot of Examples
9/25/12
Recursion
21