Lecture 16: More Recursion! CS 1110 Introduction to Computing - - PowerPoint PPT Presentation

lecture 16 more recursion
SMART_READER_LITE
LIVE PREVIEW

Lecture 16: More Recursion! CS 1110 Introduction to Computing - - PowerPoint PPT Presentation

http://www.cs.cornell.edu/courses/cs1110/2019sp Lecture 16: More Recursion! CS 1110 Introduction to Computing Using Python [E. Andersen, A. Bracy, D. Gries, L. Lee, S. Marschner, C. Van Loan, W. White] Recursion Recursive Function : A


slide-1
SLIDE 1

Lecture 16: More Recursion!

CS 1110 Introduction to Computing Using Python

[E. Andersen, A. Bracy, D. Gries, L. Lee, S. Marschner, C. Van Loan, W. White]

http://www.cs.cornell.edu/courses/cs1110/2019sp

slide-2
SLIDE 2

Recursion

Recursive Function: A function that calls itself (directly or indirectly) Recursive Definition: A definition that is defined in terms of itself

2

slide-3
SLIDE 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)! 0! = 1

3

for n > 0 Recursive case Base case What happens if there is no base case?

slide-4
SLIDE 4

Recursive Call Frames

4

factorial 1

n

3

def factorial(n): """Returns: factorial of n. Precondition: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) factorial(3)

1 2 3

slide-5
SLIDE 5

Recursive Call Frames

5

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Precondition: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

1 2 3

slide-6
SLIDE 6

Recursion

6

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Precondition: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) factorial(3)

1 2 3

Now what? Each call is a new frame.

slide-7
SLIDE 7

A:

What happens next? (Q)

7

factorial 1, 3

n

3 factorial 1

n

2 factorial 1, 3, 1

n

3 2

û B:

factorial 1

n

3

C:

factorial 1, 3, 1

n

3 2

û D:

factorial 1

n

2 ERASE FRAME factorial 1, 3

n

3

slide-8
SLIDE 8

A:

What happens next? (A)

8

factorial 1, 3

n

3 factorial 1

n

2 factorial 1, 3, 1

n

3 2

û B:

factorial 1

n

3

C:

factorial 1, 3, 1

n

3 2

û D:

factorial 1

n

2 ERASE FRAME factorial 1, 3

n

3

CORRECT

slide-9
SLIDE 9

Recursive Call Frames

9

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1

slide-10
SLIDE 10

Recursive Call Frames

10

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3

slide-11
SLIDE 11

Recursive Call Frames

11

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 1

slide-12
SLIDE 12

Recursive Call Frames

12

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 1, 3

slide-13
SLIDE 13

Recursive Call Frames

13

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 1, 3 factorial

n

1

slide-14
SLIDE 14

Recursive Call Frames

14

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 1, 3 factorial

n

1, 2

slide-15
SLIDE 15

Recursive Call Frames

15

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 1, 3 factorial

n

RETURN 1 1, 2

slide-16
SLIDE 16

Recursive Call Frames

16

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 1, 3 factorial

n

RETURN 1 1, 2

slide-17
SLIDE 17

Recursive Call Frames

17

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 RETURN 1 1, 3 factorial

n

RETURN 1 1, 2

slide-18
SLIDE 18

Recursive Call Frames

18

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2

1 2 3

1, 3 factorial

n

1 RETURN 1 1, 3 factorial

n

RETURN 1 1, 2

slide-19
SLIDE 19

Recursive Call Frames

19

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2 RETURN

1 2 3

2 1, 3 factorial

n

1 RETURN 1 1, 3 factorial

n

RETURN 1 1, 2

slide-20
SLIDE 20

Recursive Call Frames

20

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

factorial

n

2 RETURN

1 2 3

2 1, 3 factorial

n

1 RETURN 1 1, 3 factorial

n

RETURN 1 1, 2

slide-21
SLIDE 21

Recursive Call Frames

21

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

RETURN factorial

n

2 RETURN

1 2 3

2 1, 3 factorial

n

1 RETURN 1 1, 3 factorial

n

RETURN 1 1, 2 6

slide-22
SLIDE 22

Recursive Call Frames

22

factorial 1, 3

n

3

def factorial(n): """Returns: factorial of n. Pre: n ≥ 0 an int""" if n == 0: return 1 return n*factorial(n-1) Call: factorial(3)

RETURN factorial

n

2 RETURN

1 2 3

2 1, 3 factorial

n

1 RETURN 1 1, 3 factorial

n

RETURN 1 1, 2 6

slide-23
SLIDE 23

Divide and Conquer

Goal: Solve problem P on a piece of data

23

data

Idea: Split data into two parts and solve problem

data 1 data 2

Solve Problem P Solve Problem P Combine Answer!

slide-24
SLIDE 24

Example: Reversing a String

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts # 3. Combine the result

24

H e l l

  • !

!

  • l

l e H

slide-25
SLIDE 25

Example: Reversing a String

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result

25

H e l l

  • !

left right

H e l l

  • !

!

  • l

l e

If this is how we break it up…. How do we combine it?

slide-26
SLIDE 26

How to Combine? (Q)

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result

return

26

H e l l

  • !

left right

H e l l

  • !

!

  • l

l e

A: left + right B: right + left C: left D: right

slide-27
SLIDE 27

How to Combine? (A)

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result

return

27

H e l l

  • !

left right

H e l l

  • !

!

  • l

l e

A: left + right B: right + left C: left D: right

CORRECT

slide-28
SLIDE 28

Example: Reversing a String

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result return right+left

28

H e l l

  • !

left right

H e l l

  • !

!

  • l

l e

slide-29
SLIDE 29

What is the Base Case? (Q)

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result return right+left

29

H e l l

  • !

A: if s == "": return s B: if len(s) <= 2: return s C: if len(s) <= 1: return s E: A, B, and C would all work D: Either A or C would work

slide-30
SLIDE 30

What is the Base Case? (A)

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result return right+left

30

H e l l

  • !

A: if s == "": return s B: if len(s) <= 2: return s C: if len(s) <= 1: return s CORRECT E: A, B, and C would all work D: Either A or C would work

slide-31
SLIDE 31

Example: Reversing a String

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case if len(s) <= 1: return s # 2. Break into two parts left = reverse(s[0]) right = reverse(s[1:]) # 3. Combine the result return right+left

31

Base Case Recursive Case

s[0]

slide-32
SLIDE 32

Alternate Implementation (Q)

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case if len(s) <= 1: return s # 2. Break into two parts half = len(s)//2 left = reverse(s[:half]) right = reverse(s[half:]) # 3. Combine the result return right+left

32

A: YES B: NO

Does this work?

slide-33
SLIDE 33

Alternate Implementation (A)

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle base case if len(s) <= 1: return s # 2. Break into two parts half = len(s)//2 left = reverse(s[:half]) right = reverse(s[half:]) # 3. Combine the result return right+left

33

A: YES B: NO

Does this work?

CORRECT

slide-34
SLIDE 34

Alternate Implementation

34

H e l l

  • !

H e l l

  • !

H e

reverse(s[:half]) reverse(s[half:]) reverse(s[:half]) reverse(s[half:])

l

reverse(s[:half]) reverse(s[half:])

e l l

  • reverse(s[:half])

reverse(s[half:])

!

reverse(s[:half]) reverse(s[half:])

  • !

half = 3 half = 1 half = 1 half = 1 half = 1

slide-35
SLIDE 35

Alternate Implementation

35

!

  • l

l e H l e H !

  • l

H l

reverse(s[:half]) reverse(s[half:]) reverse(s[:half]) reverse(s[half:])

e

reverse(s[:half]) reverse(s[half:])

e l l !

reverse(s[:half]) reverse(s[half:])

  • reverse(s[:half])

reverse(s[half:])

  • !
slide-36
SLIDE 36
  • Example:

AMANAPLANACANALPANAMA

  • Can we define recursively?

Example: Palindromes

36

slide-37
SLIDE 37

have to be the same

Example: Palindromes

  • String with ≥ 2 characters is a palindrome if:

§ its first and last characters are equal, and § the rest of the characters form a palindrome

  • Example:

AMANAPLANACANALPANAMA

  • Implement: def ispalindrome(s):

"""Returns: True if s is a palindrome"""

has to be a palindrome

37

slide-38
SLIDE 38

Example: Palindromes

String with ≥ 2 characters is a palindrome if:

§ its first and last characters are equal, and § the rest of the characters form a palindrome

def ispalindrome(s): ends = s[0] == s[-1] middle = ispalindrome(s[1:-1]) return ends and middle

Recursive case Base case Recursive Definition

38

if len(s) < 2: return True """Returns: True if s is a palindrome"""

slide-39
SLIDE 39

Recursion and Objects

  • Class Person

§ Objects have 3 attributes § name: String § parent1: Person (or None) § parent2: Person (or None)

  • Represents the “family tree”

§ Goes as far back as known § Attributes parent1 and parent2 are None if not known

  • Constructor: Person(name,p1,p2)
  • Or Person(n) if no parents known

39

John Sr. Pamela Eva Shane Carmen John Jr. Jane Portia Ellen John III Alice John IV

slide-40
SLIDE 40

Recursion and Objects

def num_ancestors(p): """Returns: num of known ancestors Pre: p is a Person""" # 1. Handle base case. # No parents # (no ancestors) # 2. Break into two parts # Has parent1 or parent2 # Count ancestors of each one # (plus parent1, parent2 themselves) # 3. Combine the result

40

Eva Shane Carmen John Jr. Jane Portia Ellen John III Alice John IV

11 ancestors

John Sr. Pamela

slide-41
SLIDE 41

Recursion and Objects

41

Pamela Eva Shane Carmen John Jr. Jane Portia Ellen John III Alice John IV

11 ancestors def num_ancestors(p): """Returns: num of known ancestors Pre: p is a Person""" # 1. Handle base case. # No parents # (no ancestors) # 2. Break into two parts # Has parent1 or parent2 # Count ancestors of each one # (plus parent1, parent2 themselves) # 3. Combine the result parent1s = 0 if p.parent1 != None: | parent1s = 1+num_ancestors(p.parent1) parent2s = 0 if p.parent2 != None: | parent2s = 1+num_ancestors(p.parent2) if p.parent1 == None and p.parent2 == None: | return 0

John Sr.

return parent1s+parent2s

slide-42
SLIDE 42

def num_ancestors(p): """Returns: num of known ancestors Pre: p is a Person""" # 1. Handle base case. if p.parent1 == None and p.parent2 == None: return 0 # 2. Break into two parts parent1s = 0 if p.parent1 != None: parent1s = 1+num_ancestors(p.parent1s) parent2s = 0 if p.parent2 != None: parent2s = 1+num_ancestors(p.parent2s) # 3. Combine the result return parent1s+parent2s

Recursion and Objects

42

We don’t actually need this. It is handled by the conditionals in #2.

slide-43
SLIDE 43

Challenge: All Ancestors

def all_ancestors(p):

"""Returns: list of all ancestors of p""" # 1. Handle base case. # 2. Break into parts. # 3. Combine answer.

43

John Sr. Pamela Eva Shane Carmen John Jr. Jane Portia Ellen John III Alice John IV