More Recursion 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - - PowerPoint PPT Presentation

more recursion
SMART_READER_LITE
LIVE PREVIEW

More Recursion 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - - PowerPoint PPT Presentation

Lecture 15 More Recursion 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Announcements for This Lecture 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Prelim 1 0 0 0


slide-1
SLIDE 1

More Recursion

Lecture 15

slide-2
SLIDE 2

Announcements for This Lecture

Prelim 1

  • Need to be working on A4

§ Instructions are posted § Just reading it takes a while § Slightly longer than A3 § Problems are harder

  • Lab Today: lots of practice!

§ First 4 functions mandatory § Many optional ones too § Exam questions on Prelim 2

10/22/19 2 More Recursion

  • Prelim 1 back today!

§ Access in Gradescope § Solution posted in CMS § Mean: 71, Median: 74 § Spent too long on slicing

  • What are letter grades?

§ A: 80 (consultant level) § B: 60-79 (major level) § C: 35-55 (passing)

Assignments and Labs

slide-3
SLIDE 3

Recall: Divide and Conquer

Goal: Solve problem P on a piece of data

10/22/19 More Recursion 3

data

Idea: Split data into two parts and solve problem

data 1 data 2

Solve Problem P Solve Problem P Combine Answer!

slide-4
SLIDE 4

Example: Reversing a String

def reverse(s): """Returns: reverse of s Precondition: s a string""" # 1. Handle small data if len(s) <= 1: return s # 2. Break into two parts # 3. Combine the result

10/22/19 More Recursion 4

H e l l

  • !

!

  • l

l e H e l l

  • !

H !

  • l

l e H

slide-5
SLIDE 5

Example: Reversing a String

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

10/22/19 More Recursion 5

H e l l

  • !

!

  • l

l e H e l l

  • !

H !

  • l

l e H

slide-6
SLIDE 6

Example: Reversing a String

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

10/22/19 More Recursion 6

H e l l

  • !

!

  • l

l e H e l l

  • !

H !

  • l

l e H

slide-7
SLIDE 7

Example: Reversing a String

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

10/22/19 More Recursion 7

Base Case Recursive Case

slide-8
SLIDE 8

Example: Reversing a String

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

10/22/19 More Recursion 8

Base Case Recursive Case

Remove recursive call

slide-9
SLIDE 9

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 9

5 341267

Approach 1

slide-10
SLIDE 10

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 10

5 341267

Approach 1

341,267

commafy

slide-11
SLIDE 11

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 11

5 341267

Approach 1

341,267

commafy

5

slide-12
SLIDE 12

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 12

5 341267

Approach 1

341,267

commafy

5 ,

Always? When?

slide-13
SLIDE 13

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 13

5 341267

Approach 1

341,267

commafy

5 ,

Always? When?

5341 267

Approach 2

slide-14
SLIDE 14

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 14

5 341267

Approach 1

341,267

commafy

5 ,

Always? When?

5341 267

Approach 2

5,341

commafy

slide-15
SLIDE 15

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 15

5 341267

Approach 1

341,267

commafy

5 ,

Always? When?

5341 267

Approach 2

5,341

commafy

267

slide-16
SLIDE 16

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int"""

10/22/19 More Recursion 16

5 341267 341,267 ,

commafy

5341 5 267 5,341 , 267

commafy Always? When? Always!

Approach 1 Approach 2

slide-17
SLIDE 17

How to Break Up a Recursive Function?

def commafy(s): """Returns: string with commas every 3 digits e.g. commafy('5341267') = '5,341,267' Precondition: s represents a non-negative int""" # 1. Handle small data. if len(s) <= 3: return s # 2. Break into two parts left = commafy(s[:-3]) right = s[-3:] # Small part on RIGHT # 3. Combine the result return left + ',' + right

10/22/19 More Recursion 17

Base Case Recursive Case

slide-18
SLIDE 18

How to Break Up a Recursive Function?

def exp(b, c) """Returns: bc Precondition: b a float, c ≥ 0 an int"""

10/22/19 More Recursion 18

Approach 1 Approach 2 12256 = 12 × (12255)

Recursive

12256 = (12128) × (12128)

Recursive Recursive

bc = b × (bc-1) bc = (b×b)c/2 if c even

slide-19
SLIDE 19

Raising a Number to an Exponent

Approach 1

def exp(b, c) """Returns: bc Precond: b a float, c ≥ 0 an int""" # b0 is 1 if c == 0: return 1 # bc = b(bc-1) left = b right = exp(b,c-1) return left*right

Approach 2

def exp(b, c) """Returns: bc Precond: b a float, c ≥ 0 an int""" # b0 is 1 if c == 0: return 1 # c > 0 if c % 2 == 0: return exp(b*b,c//2) return b*exp(b*b,(c-1)//2)

10/22/19 More Recursion 19

slide-20
SLIDE 20

Raising a Number to an Exponent

Approach 1

def exp(b, c) """Returns: bc Precond: b a float, c ≥ 0 an int""" # b0 is 1 if c == 0: return 1 # bc = b(bc-1) left = b right = exp(b,c-1) return left*right

Approach 2

def exp(b, c) """Returns: bc Precond: b a float, c ≥ 0 an int""" # b0 is 1 if c == 0: return 1 # c > 0 if c % 2 == 0: return exp(b*b,c//2) return b*exp(b*b,(c-1)//2)

10/22/19 20

right left right left

More Recursion

slide-21
SLIDE 21

Raising a Number to an Exponent

def exp(b, c) """Returns: bc Precond: b a float, c ≥ 0 an int""" # b0 is 1 if c == 0: return 1 # c > 0 if c % 2 == 0: return exp(b*b,c//2) return b*exp(b*b,(c-1)//2)

c # of calls 1 1 2 2 4 3 8 4 16 5 32 6 2n n + 1

10/22/19 More Recursion 21

32768 is 215 b32768 needs only 215 calls!

slide-22
SLIDE 22

Recursion and Objects

  • Class Person (person.py)

§ Objects have 3 attributes § name: String § mom: Person (or None) § dad: Person (or None)

  • Represents the “family tree”

§ Goes as far back as known § Attributes mom and dad are None if not known

  • Constructor: Person(n,m,d)
  • Or Person(n) if no mom, dad

10/22/19 More Recursion 22

John Sr. Pamela Eva ??? Dan Heather John Jr. ??? ??? Jane Robert Ellen John III Alice John IV

slide-23
SLIDE 23

Recursion and Objects

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

10/22/19 More Recursion 23

John Sr. Pamela Eva ??? Dan Heather John Jr. ??? ??? Jane Robert Ellen John III Alice John IV

11 ancestors

slide-24
SLIDE 24

Recursion and Objects

def num_ancestors(p): """Returns: num of known ancestors Pre: p is a Person""" # 1. Handle small data. if p.mom == None and p.dad == None: return 0 # 2. Break into two parts moms = 0 if not p.mom == None: moms = 1+num_ancestors(p.mom) dads = 0 if not p.dad== None: dads = 1+num_ancestors(p.dad) # 3. Combine the result return moms+dads

10/22/19 More Recursion 24

John Sr. Pamela Eva ??? Dan Heather John Jr. ??? ??? Jane Robert Ellen John III Alice John IV

11 ancestors

slide-25
SLIDE 25

Is All Recursion Divide and Conquer?

  • Divide and conquer implies two halves “equal”

§ Performing the same check on each half § With some optimization for small halves

  • Sometimes we are given a recursive definition

§ Math formula to compute that is recursive § String definition to check that is recursive § Picture to draw that is recursive § Example: n! = n (n-1)!

  • In that case, we are just implementing definition

10/22/19 More Recursion 25

slide-26
SLIDE 26

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

  • Function to Implement:

def ispalindrome(s): """Returns: True if s is a palindrome"""

has to be a palindrome

10/22/19 26 More Recursion

slide-27
SLIDE 27

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): """Returns: True if s is a palindrome""" if len(s) < 2: return True # Halves not the same; not divide and conquer ends = s[0] == s[-1] middle = ispalindrome(s[1:-1]) return ends and middle

Recursive case Base case Recursive Definition

10/22/19 27 More Recursion

slide-28
SLIDE 28

Recursive Functions and Helpers

def ispalindrome2(s): """Returns: True if s is a palindrome Case of characters is ignored.""" if len(s) < 2: return True # Halves not the same; not divide and conquer ends = equals_ignore_case(s[0], s[-1]) middle = ispalindrome(s[1:-1]) return ends and middle

10/22/19 28 More Recursion

slide-29
SLIDE 29

Recursive Functions and Helpers

def ispalindrome2(s): """Returns: True if s is a palindrome Case of characters is ignored.""" if len(s) < 2: return True # Halves not the same; not divide and conquer ends = equals_ignore_case(s[0], s[-1]) middle = ispalindrome(s[1:-1]) return ends and middle

10/22/19 29 More Recursion

slide-30
SLIDE 30

Recursive Functions and Helpers

def ispalindrome2(s): """Returns: True if s is a palindrome Case of characters is ignored.""" if len(s) < 2: return True # Halves not the same; not divide and conquer ends = equals_ignore_case(s[0], s[-1]) middle = ispalindrome(s[1:-1]) return ends and middle def equals_ignore_case(a, b): """Returns: True if a and b are same ignoring case""" return a.upper() == b.upper()

10/22/19 30 More Recursion

Use helper functions!

  • Pull out anything not

part of the recursion

  • Keeps your code simple

and easy to follow

slide-31
SLIDE 31

Example: More Palindromes

def ispalindrome3(s): """Returns: True if s is a palindrome Case of characters and non-letters ignored.""" return ispalindrome2(depunct(s)) def depunct(s): """Returns: s with non-letters removed""" if s == '': return s # Combine left and right if s[0] in string.letters: return s[0]+depunct(s[1:]) # Ignore left if it is not a letter return depunct(s[1:])

10/22/19 31 More Recursion

Use helper functions!

  • Sometimes the helper is

a recursive function

  • Allows you break up

problem in smaller parts

slide-32
SLIDE 32

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Example: Space Filling Curves

  • Draw a curve that

§ Starts in the left corner § Ends in the right corner § Touches every grid point § Does not touch or cross itself anywhere

  • Useful for analysis of

2-dimensional data Challenge

Starts Here Ends Here

10/22/19 32 More Recursion

slide-33
SLIDE 33

Hilbert(1): Hilbert(2): Hilbert(n):

H(n-1) down H(n-1) down H(n-1) left H(n-1) right

Hilbert’s Space Filling Curve

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2n 2n

10/22/19 33 More Recursion

slide-34
SLIDE 34

Hilbert’s Space Filling Curve

  • Given a box
  • Draw 2n×2n

grid in box

  • Trace the curve
  • As n goes to ∞,

curve fills box Basic Idea

10/22/19 34 More Recursion

slide-35
SLIDE 35

“Turtle” Graphics: Assignment A4

10/22/19 More Recursion 35

Turn Move Change Color Draw Line