Presentation is loading. Please wait.

Presentation is loading. Please wait.

Cyriak: conceptually disruptive recursion… Baaa. Welcome to IST338… Be sure to watch your head!

Similar presentations


Presentation on theme: "Cyriak: conceptually disruptive recursion… Baaa. Welcome to IST338… Be sure to watch your head!"— Presentation transcript:

1 Cyriak: conceptually disruptive recursion… Baaa

2 Welcome to IST338… Be sure to watch your head!

3

4 We're computationally complete! IST338: now recursing… putting Python to work! Hw 2 – due Friday 2/20 ~ as usual pr1 lab – Turtle! pr2 – Monte Carlo simulation What's next? pr0 reading – Watson! Or re-cursing, depending on your feelings about recursion! pr3+4 – extra-credit probs! & adding building-blocks

5 Recursive design works… def mylen(s): """ input: any string, s output: the number of characters in s """ if s == '': return 0 else: return 1 + mylen(s[1:]) There's not much len left here! … by solving a smaller version of the same problem!

6 mylen('cs5') Behind the curtain: how recursion works... def mylen(s): if s == '': return 0 else: return 1 + mylen(s[1:]) 1 + mylen('s5') 1 + 1 + mylen('5') 1 + 1 + 1 + mylen('') 1 + 1 + 1 + 0

7 mymax( [1,4,3,42,-100,7] ) def mymax(L): if len(L) == 1: return L[0] elif L[0] < L[1]: return mymax( L[1:] ) else: return mymax( L[0:1]+L[2:] ) mymax( [4,3,42,-100,7] ) mymax( [4,42,-100,7] ) mymax( [42,-100,7] ) mymax( [42,7] ) mymax( [42] ) 42 base case drop 1st drop 2nd

8 Picture it! power(2,5) -> 2*2 power(2,0) -> 1 2 0 == 12 5 2*2* 2 4 2 p 2*2* 2 4 power(2,p) -> 2*power(…,…) Do you see the call to power!? def power(b,p): """ returns b to the p power Use recursion, not ** Inputs: int b, int p: the base and the power """ What should this be? power(b,p) ->

9 Picture it! power(2,5) -> 2*2 power(2,0) -> 1 2 0 == 12 5 2*2* 2 4 2 p 2*2* 2 4 power(2,p) -> 2*power(…,…) Do you see the call to power!? Try it! def power(b,p): Handle negative p values w/elif. """ returns b to the p power Use recursion, not ** Inputs: int b, int p: the base and the power """ Want more power? E.g., power(5,-1) == 0.2 if : Base case test p == 0 return else: return Base case Recursive case What should this be? power(b,p) ->

10 power( 2, 5 ) 2* power( 2, 4 ) 2* 2* power( 2, 3 ) 2* 2* 2* power( 2, 2 ) 2* 2* 2* 2* power( 2, 1 ) 2* 2* 2* 2* 2* power( 2, 0 ) 2* 2* 2* 2* 2* 1 32

11 Picture it! sajak('') 0 NOT a space – this is no characters at all. This is the empty string – and it has 0 vowels! def sajak(s): """ returns the number of vowels in the input string, s """ '' sajak('okay') 1+sajak( ) 'okay' sajak('what') 0+sajak( ) 'what' starts with a vowel – count that vowel and delegate the rest to recursion starts with a consonant – so skip it and delegate the rest!

12 Picture it! sajak('') 0 NOT a space – this is no characters at all. This is the empty string – and it has 0 vowels! def sajak(s): What 7-letter English word w maximizes sajak(w) ? """ returns the number of vowels in the input string, s """ Want more Pat? if s == '' : elif else: return Base case test '' sajak('okay') 1+sajak( ) 'okay' sajak('what') 0+sajak( ) 'what' starts with a vowel – count that vowel and delegate the rest to recursion Try it! starts with a consonant – so skip it and delegate the rest!

13 sajak( 'eerier' ) 1+ sajak( 'erier' ) 1+ 1+ sajak( 'rier' ) 1+ 1+ 0+ sajak( 'ier' ) 1+ 1+ 0+ 1+ sajak( 'er' ) 1+ 1+ 0+ 1+ 1+ sajak( 'r' ) 1+ 1+ 0+ 1+ 1+ 0+ sajak( '' ) 1+ 1+ 0+ 1+ 1+ 0+ 0 4

14 def power(b,p): """ inputs: base b and power p (an int) implements: b**p """ if p == 0: return 1.0 elif p < 0: return ____________________ else: return b * power(b,p-1) Recursion is power!

15 # of vowels in s sajak(s): Base case? When there are no letters, there are ZERO vowels if s[0] is NOT a vowel, the answer is Rec. step? Look at the initial character. if s[0] is a vowel, the answer is DESIGNDESIGN sajak( s[1:] ) 1 + sajak( s[1:] )

16 def sajak(s): if s == '': return 0 elif s[0]=='a' or s[0]=='e' or… but how to check for vowels? Is s[0] a vowel?

17 Python is… in >>> 'i' in 'team' False >>> 'cs' in 'physics' True >>> 42 in [41,42,43] True >>> 42 in [[42], '42'] False I guess Python's the in thing >>> 'i' in 'alien' True >>> 3*'i' in 'alien' False

18 def sajak(s): if len(s) == 0: return 0 elif s[0] in 'aeiou': return 1 + sajak(s[1:]) else: return 0 + sajak(s[1:]) if s[0] is NOT a vowel, the answer is just the number of vowels in the rest of s if s[0] IS a vowel, the answer is 1 + the # of vowels in the rest of s Base Case Recursive Cases let's input 'eerier' for s

19 The key to understanding recursion is, first, to understand recursion. - a former student tutors @ LAC all week! Good luck with Homework #1 It's the eeriest!

20 Three random asides… import random choice( L ) choice(['cmc','scripps','pitzer','pomona']) chooses 1 element from the sequence L allows use of dir(random) and help(random) How could you get a random int from 0 to 99 inclusive? from random import * all random functions are now available! choice('mudd') uniform(low,hi) chooses a random float from low to hi floats have 16 places of precision Aargh – so close! range(1,5)[1,2,3,4]

21 A random function… print the guesses ? return the number of guesses ? from random import * def guess( hidden ): """ tries to guess our "hidden" # """ compguess = choice( range(100) ) if compguess == hidden: # at last! print 'I got it!' else: guess( hidden ) Suspicious? I am! slow down… investigate expected # of guesses?!?? Remember, this is [0,1,…,99]

22 Empirical Hypothesis Testing… a.k.a. How many guesses do we expect in order to find the correct number?

23 from random import * import time def guess( hidden ): """ guessing game """ compguess = choice( range(100) ) # print 'I choose', compguess # time.sleep(0.05) if compguess == hidden: # at last! # print 'I got it!' return 1 else: return 1 + guess( hidden ) Recursive guess-counting

24 A few random thoughts… choice( range(1,5)+[4,2,4,2] ) uniform( -20.5, 0.5 ) What are the chances this returns a 2 ? from random import * What're the chances of this being > 0? choice( '1,2,3,4' ) choice( ['1,2,3,4'] ) choice( '[1,2,3,4]' ) choice( [1,2,3,2] ) choice( range(5) ) What's the most likely return value here? Quiz Name(s): What's the most likely return value here? What are the chances of this returning a 4 ? Is this more likely to be even or odd (or same)? Careful! Extra! choice( 0,1,2,3,4 ) choice[ range(5) ] choice( [range(5)] ) Which two of these are syntax errors? What does the third, "correct" one do? and how likely are all these?

25 [ [0,1,2,3,4] ] choice( range(1,5)+[4,2,4,2] ) uniform( -20.5, 0.5 ) What are the chances this returns a 2 ? What're the chances of this being > 0? choice( '1,2,3,4' ) choice( ['1,2,3,4'] ) choice( '[1,2,3,4]' ) choice( [1,2,3,2] ) choice( range(5) ) What's the most likely return value here? What are the chances of this returning a 4 ? Is this more likely to be even or odd (or same)? 1/42 choice( 0,1,2,3,4 ) choice[ range(5) ] choice( [range(5)] ) and how likely are all these? 2/4 or 50% 3/8 ',' 3/7 '1,2,3,4' 1/1 ',' 3/9 even 3/5 [0,1,2,3,4] syntax error correct: always returns [0,1,2,3,4] syntax error 1/1 chance [1,2,3,4,4,2,4,2] Data is in black. Probabilities are in blue.

26 The two Monte Carlos Monte Carlo casino, Monaco Insights via random trials Monte Carlo methods, Math/CS and their denizens…

27 Insights via random trials Monte Carlo casino, Monaco Monte Carlo methods, Math/CS Stanislaw Ulam (Los Alamos badge) Bond, James Bond The two Monte Carlos and their denizens… Ulam, Stan Ulam

28 Monte Carlo in action def countDoubles( N ): """ input: the # of dice rolls to make output: the # of doubles seen """ if N == 0: return 0 # zero rolls, zero doubles… else: d1 = choice( [1,2,3,4,5,6] ) d2 = choice( range(1,7) ) if d1 != d2: return 0+countDoubles( N-1 ) # don't count it else: return 1+countDoubles( N-1 ) # COUNT IT! two dice from 1-6 inclusive where and how is the check for doubles? N is the total number of rolls How many doubles will you get in N rolls of 2 dice?

29 Empirical Hypothesis Testing… a.k.a. How many guesses do we expect in order to find the correct number?

30 Empirical Hypothesis Testing… a.k.a. Run it a zillion times! # this line runs guess(42) 1000 times! LC = [ guess(42) for x in range(1000) ] # Let's look at the first 10 of them: print LC[0:10] # Let's find the average: print "av. guesses:", sum(LC)*1.0/len(LC) Hah! Now I see why they told me I'd be making a zillion euros!

31 Empirical Hypothesis Testing… a.k.a. How likely are we to roll doubles on two six-sided dice? Hah! Now I see why they told me I'd be making a zillion euros!

32 Zillion-times testing! # this runs the doubles-counter 600 times… cd( 600 ) # Run _that_ 100 times (60,000 rolls total!) DBLS = [ cd(600) for x in range(100) ] # Look at the first 10 of these print DBLS[0:10] # Let's find the average: print "av. dbls/600:", sum(DBLS)*1.0/len(DBLS) needed a less continental name…

33 On balance? or maybe lighter is better?

34 Data Functions …together [8,9,10] sq( ) [64,81,100] [ sq(x) for x in [8,9,10] ]

35 List Comprehensions >>> [ 2*x for x in [0,1,2,3,4,5] ] What's the syntax saying here? List Comprehenion result [0, 2, 4, 6, 8, 10]

36 List Comprehensions >>> [ 2*x for x in [0,1,2,3,4,5] ] [0, 2, 4, 6, 8, 10] output input The same as map, only better! this "runner" variable can have any name... x takes on each value and 2*x is output for each one

37 List Comprehensions >>> [ 10*x for x in [0,1,2,3,4,5] if x%2==0] result >>> [ y*21 for y in range(0,3) ] LC result >>> [ s[1] for s in ["hi", "5Cs!"] ] result LC OK – got it. But what about that name?

38 List Comprehensions? >>> [ 2*x for x in [0,1,2,3,4,5] ] [0, 2, 4, 6, 8, 10] Is this really the best name Guido Van Rossum could think of?

39 List Comprehensions? >>> [ 2*x for x in [0,1,2,3,4,5] ] [0, 2, 4, 6, 8, 10] FunLists! Datafuncs? Google map s? A list comprehension by any other name would be as sweet…

40 [ n**2 for n in range(0,5) ] Quiz! [ a*(a-1) for a in range(8) if a%2==1 ] [ -7*b for b in range(-6,6) if abs(b)>4 ] [ s[1::2] for s in ['aces','451!'] ] [ 42 for z in [0,1,2] ] A range of list comprehensions... Write Python's result for each L.C.: [ z for z in [0,1,2] ] I wonder if these will be useful ?! Name(s): ___________________________

41 Syntax ?! a (frustrated!) rendering of an unfamiliar math problem >>> [ 2*x for x in [0,1,2,3,4,5] ] [0, 2, 4, 6, 8, 10] at first… a jumble of characters and random other stuff

42 Syntax ?! a (frustrated!) rendering of an unfamiliar math problem >>> [ 2*x for x in [0,1,2,3,4,5] ] [0, 2, 4, 6, 8, 10] at first… a jumble of characters and random other stuff

43 Syntax ~ is CS's key resource! a (frustrated!) rendering of an unfamiliar math problem which was likely similar to these… Where'd the change happen?

44 Syntax vs. Semantics Plus – you might consider coming to the Career Fair this Friday at HMC's LAC…

45 Another Monte Carlo Monty… ? inspiring the “Monty Hall paradox”

46 Let's make a deal… '63-'86 inspiring the Monty Hall paradox Monty

47 Let's make a deal: XKCD's take… … but what if you considered the goat the grand prize!? inspiring the Monty Hall paradox Monty

48 Monte Carlo Monty Hall Suppose you always switch to the other door... What are the chances that you will win the prize ? Run it (randomly) 300 times and see!

49 Monte Carlo Monty Hall def MCMH( init, sors, N ): """ plays the "Let's make a deal" game N times returns the number of times you win the *Spam!* """ if N == 0: return 0 # don't play, can't win przDoor = choice([1,2,3]) # where the spam (prize) is… if init == przDoor and sors == 'stay': result = 'Spam!' elif init == przDoor and sors == 'switch': result = 'pmfp.' elif init != przDoor and sors == 'switch': result = 'Spam!' else: result = 'pmfp.' print 'You get the', result if result == 'Spam!': return 1 + MCMH( init, sors, N-1 ) else: return 0 + MCMH( init, sors, N-1 ) Your initial choice! 'switch' or 'stay' number of times to play

50 CS for Insight! a.k.a. How often do we win if we SWITCH vs. STAY ? I hope the prize isn't in Euros!

51 Monte Carlo Monty Hall! # this runs the game once (staying…) MCMHonce1( 3, 'stay' ) # Run _that_ 3000 times PRIZES = [ MCMH1(3,'stay') for x in range(3000) ] # Look at the first 10 of these print PRIZES[0:10] # Let's find the total number of wins: how to do this… ?!

52 A B C D E F G H 0 1 2 34 5 6 7 8 9

53 A B C D E F G H 0 1 2 34 5 6 7 8 9

54 An example closer to home... 25262728502423220 An overworked CGU student (S) leaves Harg. after their "late-night" breakfast. Each moment, they randomly stumble toward class (W) or their Apartment (E) ACB Apt (S) (W) Harg. Write a program to model and analyze! this scenario... Once the student arrives at the dorm or classroom, the trip is complete. The program should then print the total number of steps taken. hw2pr2 rwpos(s,nsteps)rwsteps(s,low,hi) take nsteps random steps starting at s take random steps starting at s until you reach either low or hi S

55 An example closer to home... 25262728502423220 An overworked CGU student (S) leaves Harg. after their "late-night" breakfast. Each moment, they randomly stumble toward class (W) or their Apartment (E) ACB Apt (S) (W) Harg. Write a program to model and analyze! this scenario... Once the student arrives at the dorm or classroom, the trip is complete. The program should then print the total number of steps taken. hw2pr2 rwpos(s,nsteps)rwsteps(s,low,hi) take nsteps random steps starting at s take random steps starting at s until you reach either low or hi S How could we create this as an "ASCII" animation?

56 Nature prefers recursion, too! Recursion's challenge? You need to see BOTH the self-similar pieces AND the whole thing simultaneously!

57

58 Yes... and no.Are these rules for real?

59 Dragon's-blood Tree

60 There still has to be a base case…

61 or else!

62 Cyriak: conceptually disruptive recursion… is the branching, not the single-path variety. handfingers

63 Python's Etch-a-Sketch the turtle's canvas import time from turtle import * def draw(): shape('turtle') # pause time.sleep(2) # drawing… width(5) left(90) forward(50) right(90) backward(50) down() or up() color('darkgreen') tracer(1) or tracer(0) width(5) http://docs.python.org/library/turtle.html degrees! sets if the pen draws or not sets if the pen animates or not (0,0) window_height() window_width() (42,42) pixels!

64 Single-path recursion def tri(): """ a triangle! """ forward(100) left(120) forward(100) left(120) forward(100) left(120) Let's tri this with recursion: (1) How about any regular N-gon? (2) I don't know about tri, but there sure is NO return … ! def tri( n ): """ draws a triangle """ if n==0: return else: forward(100) # one side left(120) # turn 360/3 tri( n-1 ) # draw rest def poly(n, N): """ draws a triangle """ if n==0: return else: forward(100) # one side left(360.0/N) # turn 360/N poly(n-1, N) # draw rest

65 def chai(size): """ mystery! """ forward(size) left(90) forward(size/2.0) right(90) forward(size) left(90) forward(size/2.0) right(90) backward(size) What does chai(100) draw? (1) Be the turtle ! Finish rwalk so it draws a "stock-market" path: N steps of 10 pixels each. Use recursion. (2) from random import * def rwalk(N): """ make N 10-pixel steps, NE or SE """ if N == 0: return elif choice(['left','right']) == 'left': else: # this handles 'right' Extra! How could you make it a bull (or a bear) market? one possible result of rwalk(20) left(45) forward(10) What if you called chai(size/2) betw. the right(90) & left(90) calls? ? ? Extra!

66 def chai(size): """ mystery! """ if size<9: return forward(size) left(90) forward(size/2.0) right(90) forward(size) left(90) forward(size/2.0) right(90) backward(size) How could you add more to each T-tip?Why are there two identical commands in a row ~ twice!? (1) What does chai(100) do?

67 from random import * def rwalk(N): """ make N 10-px steps, NE or SE """ if N == 0: return elif choice(['left','right'])=='left': left(45) forward(10) right(45) rwalk( N-1 ) else: # 'right' right(45) forward(10) left(45) rwalk( N-1 ) What if we didn't turn back to face east each time? (2) rwalk is a random stock market walk... Extra: Creating a bull (or a bear) market?

68 hw2pr1 100 81 spiral( initLength, angle, multiplier ) spiral(100,90,0.9) 90 fractal art!

69 svtree( trunkLength, levels ) svtree( 100, 5 ) levels == 5 levels == 2 levels == 0 (no drawing) levels == 1 levels == 3 levels == 4

70 svtree( trunkLength, levels ) svtree( 100, 5 ) levels == 5 levels == 2 levels == 0 (no drawing) levels == 1 svtree( 75, 4 ) What steps does the turtle need to take before recursing? levels == 3 levels == 4

71 svtree( trunkLength, levels ) levels == 5 levels == 4 levels == 3 levels == 2 levels == 0 (no drawing) Be sure the turtle always returns to its starting position! levels == 1 svtree( 100, 5 ) step #1: go forward… step #2: turn a bit… step #3: draw a smaller svtree! step #4: turn to another heading step #5: draw another smaller svtree! step #6: get back to the start by turning and moving!

72 svtree( trunkLength, levels ) svtree( 100, 5 ) levels == 5 levels == 2 levels == 0 (no drawing) levels == 1 svtree( 75, 4 ) Be sure the turtle always returns to its starting position! that means it will finish the recursive call right here! levels == 3 levels == 4

73 The Koch curve snowflake(100, 0)snowflake(100, 1)snowflake(100, 2) snowflake(100, 3)snowflake(100, 4)snowflake(100, 5)

74 Recursive art? Create your own… hw2pr4 Happy turtling! What? Way too happy to be art… My recursive compositions burninate even Cyriak's brain! seven-cornered confetti

75

76 A B C D E F G H 0 1 2 34 5 6 7 8 9

77 Data Functions [13,14,15] sum( ) [3,4,5,6,7,8,9]

78 sum range def sum(L): """ input: L, a list of #s output: L's sum """ if len(L) == 0: return 0.0 else: return L[0] + sum(L[1:]) Base Case Recursive Case

79 def range(low,hi ): """ input: ints low and hi output: int list from low to hi """ if low >= hi: return [] else: return what's cookin' here? excluding hi sum range step?

80 >>> sum(range(1,101)) ? sum and range I'd bet you have a 50/50 chance on this one… - Ben. L '14 1784

81 >>> sum(range(1,101)) ? sum and range I'd bet you have a 50/50 chance on this one… - Ben. L '14 1784 and 100 more… http://www.americanscientist.org/template/AssetDetail/assetid/50686 Gauss's storied story…

82 sum and range Looks sort of scruffy for a 7-year old… ! and 100 more… http://www.americanscientist.org/template/AssetDetail/assetid/50686 1784 >>> sum(range(1,101)) 5050 Gauss's storied story…

83 Welcome to CS 5! Be sure to watch your head…

84

85 Designing with LCs >>> [ _______ for x in range(4) ] [0, 14, 28, 42] >>> [ _____________ for c in 'igetthis' ] [True, False, False, False, False, False, True, False] [ 1, 0, 0, 0, 0, 0, 1, 0 ] output input And what if we wanted these values in red…? [0,1,2,3]

86 LC = [1 for x in L] return sum( LC ) myst1(L): def [7,8,9] But one-liners are my specialty… Sweet! Using LCs LC = [letScore(c) for c in S] return sum( LC ) myst2(S): def 'twelve' lots of ifs… return score letScore(c): def

87 LC = [1 for x in L] return sum( LC ) len(L): def [7,8,9] But one-liners are my specialty… Sweet! Using LCs LC = [letScore(c) for c in S] return sum( LC ) scrabbleScore(S): def 'twelve' lots of ifs… return score letScore(c): def

88 stuff to get score… return score letScore(c): scrScore(s): LC = [ letScore(c) for c in s] return sum( LC ) def scrabble score! 'twelve' Using LCs

89 LC = [1 for x in L] return sum( LC ) len(L): def But in one-line … ? 'cs5' len(L): def return sum([1 for x in L]) Maybe too terse! Sweet! "One-line" LCs

90 count(e,L): LC = [ 1 for x in L if ] return sum( LC ) def sajak(s): LC = [ for c in s] return sum( LC ) # of vowels Remember True == 1 and False == 0 def 'sequoia' count(e,L): # of times e is in L LC = [ for x in L ] return sum( LC ) def [3,42,5,7,42] 42 using if instead…

91 Go! Write each of these functions using list comprehensions… def nodds(L): def lotto(Y,W): input: L, any list of #s output: the # of odd #s in L example: nodds( [3,4,5,7,42] ) == 3 inputs: Y and W, two lists of "lottery" numbers (ints) output: the # of matches between Y & W example: lotto( [5,7,42,47], [3,5,7,44,47] ) == 3 Y are your #sW are the winning #s def ndivs(N): input: N, an int >= 2 output: the # of positive divisors of N example: numdivs(12) == 6 (1,2,3,4,6,12) LC = [ for x in L ] return sum(LC) def primesUpTo(P): input: P, an int >= 2 output: the list of prime #s up to + incl. P example: primesUpTo(12) == [2,3,5,7,11] Extra! LC = [

92 output: the # of odd #s in L def nodds(L): inputs: L, any list of #s example: nodds( [3,4,5,7,42] ) == 3 LC = [ for x in L ] return sum(LC) def nodds(L): LC = [ 1 for x in L ] return sum(LC)

93 def lotto(Y,W): LC = [ for w in W ] return sum(LC) def lotto(Y,W): LC = [ 1 for w in W ] return sum(LC) inputs: Y and W, two lists of "lottery" numbers (ints) output: the # of matches between Y & W example: lotto( [5,7,42,47], [3,5,7,44,47] ) == 3 Y are your #sW are the winning #s … could adapt to "y in Y", too.

94 def ndivs(N): LC = [ for n in range(1,N+1)] return sum(LC) input: N, an int >= 2 output: the # of positive divisors of N example: numdivs(12) == 6 (1,2,3,4,6,12) def primesUpto( P ): Extra! A list of all primes up to P…

95 Turtle happiness? remember you can run done() after turtle drawing! This releases control of the turtle window to the computer (the operating system). To be honest, it seems that not every machine needs this…

96 We're computationally complete! CS 5: now recursing… putting Python to work! Hw 2 – due Sunday evening ~ usual time pr1 lab – Turtle! pr2, pr3 - Python probs… What's next? pr0 reading – Watson! Or re-cursing, depending on your feelings about recursion! pr4 – extra-credit turtle… ! & adding building-blocks

97 Recursive Art ~ hw2pr4 Submit things that work … … and even things that don't! septagonal confetti Cyriak's pet snake…

98 On-campus tutoring hours… ! CMC: Scripps: Pitzer! Pomona: Beckett Lounge, Mon 6-8 (Melody S) CSMath CR, Adams Hall, Sun 8-10 (Rachel L & Justin A) Edmunds, Sun 8-10 (Kim R) Scripps Student Union, Sun 6-8 (Kate F) Phillips Lounge, Sun 3-5 (Michael I) Beckett Lounge, Sat + Sun 1-3 (Melody S) Motley, Thu 8-10 (Kate F)

99 Picture it! Try it! def power(b,p): Handle negative values of p in an elif. """ returns b to the p power Use recursion, not ** Inputs: int b, int p: the base and the power """ Want more power? power(2,5) -> 2*2 For example, power(5,-1) == 0.2 if : Base case test p == 0 return else: return Base case Recursive case power(2,0) -> 1 2 0 == 12 5 2*2* 2 4 2 p 2*2* 2 4 power(2,p) -> 2*power(…) Do you see the call to power!?

100 Using a Euro, Yuan the deadline comes next time I'll try to make the Mark. I'm Pounding it into my brain, but I have to Peso much attention to other deadlines in the classes I Currency have - but if this keeps up, my grade will be demolished into Rubles. hw0 highlights and thoughts… Eric Nguyen Ashraf Mathkour Martha Parker ! 11:59 !?

101 Using a Euro, Yuan the deadline comes next time I'll try to make the Mark. I'm Pounding it into my brain, but I have to Peso much attention to other deadlines in the classes I Currency have - but if this keeps up, my grade will be demolished into Rubles. hw0 highlights and thoughts… Eric Nguyen Ashraf Mathkour Martha Parker ! 11:59 !? on-campus tutoring! (details Wed. …)

102 Run inside Sublime!? not required + not universal -- but you may want to try it… Python interpreter Python source instructions are at the start of this week's Lab…

103 Try it! def power(b,p): Handle negative values of p in an elif. """ returns b to the p power Use recursion, not ** Inputs: int b, int p: the base and the power """ Want more power? power(2,5) == 32.0 For example, power(5,-1) == 0.2 def sajak(s): sajak('wheel of fortune') == 6 What 7-letter English word w maximizes sajak(w) ? What about y? You decide… """ returns the number of vowels in the input string, s """ Want more Pat? if : if s == '' : Base case test elif else: p == 0 return else: return Base case test elif in general:

104 Picture it! def mylen(s): """ returns the number of characters in s input: s, a string """ mylen('') 0 NOT a space – this is no characters at all. This is the empty string – and it has length of 0! s = '' mylen('hi') 1+mylen( ) mylen('recursion') 1+mylen( ) s = 'recursion' starts with a vowel – count that vowel and delegate the rest to recursion wow! s = 'hi' if : Base case test p == 0 return else: return Base case Recursive case

105 Design #2 def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """ if : elif : base case test! another case… len(L)==1 [1,4,3,42,-100,7] return else:

106 def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """ if len(L) == 1: return L[0] elif L[0] < L[1]: return mymax( L[1:] ) else: return mymax( L[0:1] + L[2:] ) Hey - do I get a slice?! Design #2

107 Computation's Dual Identity name: x type: int LOC: 300 41 memory location 300 ComputationData Storage name: y type: int LOC: 304 42 memory location 304 Last time variables ~ boxes But what does all this stuff look like ?

108 Giving names to data def flipside(s): """ flipside(s): swaps s's sides! input s: a string """ x = len(s)/2 return s[x:] + s[:x] This idea is the key to your happiness!

109 Hey - I'm happy about this, too! Why would computers "prefer" the top version, too? def flipside(s): x = len(s)/2 return s[x:] + s[:x] def flipside(s): return s[len(s)/2:] + s[:len(s)/2] Use variables! Avoid this approach…

110 control-b in Sublime Test! def flipside(s): """ flipside(s): swaps s's sides! input s: a string """ x = len(s)/2 return s[x:] + s[:x] # # Tests! # print "flipside('carpets') ~", flipside('carpets') (1) function definition (2) function tests We provide these tests (for now…) but don't test like this!

111 def convertFromSeconds(s): # total seconds """ convertFromSeconds(s): Converts an integer # of seconds into a list of [days, hours, minutes, seconds] input s: an int """ seconds = s % 60 # leftover seconds m = s / 60 # total minutes minutes = m % 60 # leftover minutes h = m / 60 # total hours hours = h % 24 # leftover hours days = h / 24 # total days return [days, hours, minutes, seconds] This program uses variables constantly! Using variables…

112 def convertFromSeconds(s): # total seconds """ convertFromSectons(s): Converts an integer # of seconds into a list of [days, hours, minutes, seconds] input s: an int """ seconds = s % 60 # leftover seconds m = (s / 60) # total minutes minutes = m % 60 # leftover minutes h = m / 60 # total hours hours = h % 24 # leftover hours days = h / 24 # total days return [days, hours, minutes, seconds] How functions look… docstring comments – these are mostly optional in CS 5 code block return statement name input(s)

113 Computation's Dual Identity name: x type: int LOC: 300 41 memory location 300 ComputationData Storage name: y type: int LOC: 304 42 memory location 304 variables ~ boxes accessed through functions… Functions! It's no coincidence this starts with fun!

114 Functioning across disciplines def g(x): return x**100 g(x) = x 100 CS's googolizerMath's googolizer defined by what it does defined by what it is + how efficiently it works procedurestructure

115 How functions work… def f(x): return 11*g(x) + g(x/2) What is demo(-4) ? def demo(x): return x + f(x) def g(x): return -1 * x I might have a guess… Quiz First and last name(s): -4

116 How functions work… def f(x): return 11*g(x) + g(x/2) >>> demo(-4) ? def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) def g(x): return -1 * x Hey! This must be a stack-frame frame! stack frame

117 def f(x): return 11*g(x) + g(x/2) def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f x = -4 return 11*g(x) + g(x/2) def g(x): return -1 * x >>> demo(-4) ? How functions work… stack frame

118 def f(x): return 11*g(x) + g(x/2) def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f x = -4 return 11*g(x) + g(x/2) def g(x): return -1 * x >>> demo(-4) ? How functions work… These are distinct memory locations both holding x 's. stack frame

119 def f(x): return 11*g(x) + g(x/2) def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f g x = -4 return 11*g(-4) + g(-4/2) x = -4 return -1.0 * x def g(x): return -1 * x >>> demo(-4) ? How functions work… stack frame

120 def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f g x = -4 return 11* 4 + g(-4/2) x = -4 return -1 * -4 4 >>> demo(-4) ? How functions work… done! stack frame

121 def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f x = -4 return 11* 4 + g(-4/2) >>> demo(-4) ? How functions work… the "return value" stack frame

122 def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f g x = -4 return 11* 4 + g(-4/2) x = -2 return -1 * -2 2 >>> demo(-4) ? How functions work… These are distinct memory locations both holding x 's – and now they also have different values!! stack frame

123 def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f x = -4 return 11* 4 + 2 >>> demo(-4) ? How functions work… the "return value" stack frame

124 def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f x = -4 return 11* 4 + 2 46 >>> demo(-4) ? How functions work… stack frame

125 def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + 46 42 >>> demo(-4) 42 How functions work… stack frame

126 Function stacking def f(x): return 11*g(x) + g(x/2) def g(x): return -1 * x def demo(x): return x + f(x) demo x = -4 return -4 + f(-4) f g x = -4 return 11* 4 + g(-4/2) x = -2 return -1 * -2 2 (1) keeps separate variables for each function call… (2) remembers where to send results back to… "The stack" is a memory area that the stack stack frame

127 return > print >>> ans = dbl(21) def dbl(x): """ dbls x? """ return 2*x def dblPR(x): """ dbls x? """ print 2*x >>> ans = dblPR(21)

128 >>> ans = dbl(21) def dbl(x): """ dbls x? """ return 2*x def dblPR(x): """ dbls x? """ print 2*x >>> ans = dblPR(21) return yields the function call's value … print just prints stuff to the screen... … which the shell then prints! return > print

129 Function design

130 Thinking sequentially 5 ! = 5 * 4 * 3 * 2 * 1 N ! = N * (N-1) * (N-2) * … * 3 * 2 * 1 factorial 5 ! = 120

131 factorial 5 ! = 5 * 4 * 3 * 2 * 1 N ! = N * (N-1) * (N-2) * … * 3 * 2 * 1 5 ! = 120 March + beyond… Thinking sequentially

132 Recursion == self-reference! 5 ! = N ! = Thinking recursively 5 ! = 5 * 4 * 3 * 2 * 1 N ! = N * (N-1) * (N-2) * … * 3 * 2 * 1 factorial 5 ! = 120

133 Warning: this is legal! def fac(N): return N * fac(N-1) I wonder how this code will STACK up!?

134 def fac(N): return N * fac(N-1) The calls to fac will never stop: there's no BASE CASE! Make sure you have a base case, then worry about the recursion... legal != recommended

135 def fac(N): return fac(N) Roadsigns and recursion examples of self-fulfilling danger This runs ~ but does not help!

136 Recursion's advantage: It handles arbitrary structural depth – all at once! As a hat, I'm recursive, too!

137 The dizzying dangers of having no base case!

138

139 def fac(N): if N <= 1: return 1 Thinking recursively Base case

140 def fac(N): if N <= 1: return 1 Thinking recursively Base case "How could I use the factorial of anything smaller than N?" Then do! Ask yourself:

141 def fac(N): if N <= 1: return 1 else: return N*fac(N-1) Recursive case (shorter) Human: Base case and 1 stepComputer: Everything else Base case Thinking recursively

142 def fac(N): if N <= 1: return 1 else: rest = fac(N-1) return rest * N Recursive case (clearer, for some) Human: Base case and 1 stepComputer: Everything else Base case Thinking recursively

143 Behind the curtain… fac(5) def fac(N): if N <= 1: return 1 else: return N * fac(N-1)

144 fac(5) 5 * fac(4) Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1)

145 fac(5) 5 * fac(4) 4 * fac(3) Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) 5 * Operation waiting …

146 fac(5) 5 * fac(4) 4 * fac(3) 3 * fac(2) Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) 5 * 5 * 4 * More operations waiting…

147 fac(5) 5 * fac(4) 4 * fac(3) 3 * fac(2) 2 * fac(1) Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) 5 * 5 * 4 * 5 * 4 * 3 *

148 fac(5) 5 * fac(4) 4 * fac(3) 3 * fac(2) 2 * fac(1) 1 "The Stack" Stack frames hold all of the individual calls to fac Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) N=5 N=4 N=3 N=2 N=1 5 different N's are living in memory… 5 * 5 * 4 * 5 * 4 * 3 * 5 * 4 * 3 * 2 *

149 fac(5) 5 * fac(4) 4 * fac(3) 3 * fac(2) 2 * 1 Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) 5 * 5 * 4 * 5 * 4 * 3 *

150 fac(5) 5 * fac(4) 4 * fac(3) 3 * 2 Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) 5 * 5 * 4 *

151 fac(5) 5 * fac(4) 4 * 6 Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1) 5 *

152 fac(5) 5 * 24 Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1)

153 fac(5) Result: 120 0 x*** -> N 0 0 N*** -> X 1 Look familiar? Recursive step Base case show facWPR … Behind the curtain… def fac(N): if N <= 1: return 1 else: return N * fac(N-1)

154 Thinking recursively… What will print when facWPR(5) is called?

155 def fac(N): if N <= 1: return 1 else: rest = fac(N-1) return rest * N You handle the base case – the easiest case! Recursion does almost all of the rest of the problem! You specify one step at the end Let recursion do the work for you. Exploit self-similarity Produce short, elegant code Less work !

156 But you do need to do one step yourself… def fac(N): if N <= 1: return 1 else: return fac(N) This will not work !

157 Nature prefers recursion, too! Recursion's challenge? You need to see BOTH the self-similar pieces AND the whole thing simultaneously!

158

159 Yes... and no.Are these rules for real?

160 Dragon's-blood Tree

161 There still has to be a base case…

162 or else!

163 Recursive design… (2) Find the self-similarity. (1) Program the base case. (3) Do one step! (4) Delegate the rest to recursion… fun! easy!? cool! Aha! indexing and slicing

164 One step? …is easy to do with Python s = 'aliens' How do we get at the initial character of s? L = [ 42, 21 ] How do we get at ALL THE REST of s? s[0] L[0] s[ ] L[ ] How do we get at the initial element of L? How do we get at ALL THE REST of L? 'liens' [ 21 ]

165 Recursive design #1 def mylen(s): """ input: any string, s output: the number of characters in s """ if : else: base case test! 'cs5' "How could I make use of the length of something smaller than s?" Then do! Ask yourself: return

166 … complete def mylen(s): """ input: any string, s output: the number of characters in s """ if s == '': return 0 else: return 1 + mylen(s[1:]) There's not much len left here!

167 mylen('cs5') Behind the curtain: how recursion works... def mylen(s): if s == '': return 0 else: return 1 + mylen(s[1:]) 1 + mylen('s5') 1 + 1 + mylen('5') 1 + 1 + 1 + mylen('') 1 + 1 + 1 + 0

168 Looking behind the curtain… http://www.pythontutor.com/visualize.html

169 Design #2 def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """ if : elif : base case test! another case… len(L)==1 [1,4,3,42,-100,7] return else:

170 def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """ if len(L) == 1: return L[0] elif L[0] < L[1]: return mymax( L[1:] ) else: return mymax( L[0:1] + L[2:] ) Hey - do I get a slice?! Design #2

171 mymax( [1,4,3,42,-100,7] ) def mymax(L): if len(L) == 1: return L[0] elif L[0] < L[1]: return mymax( L[1:] ) else: return mymax( L[0:1]+L[2:] ) mymax( [4,3,42,-100,7] ) mymax( [4,42,-100,7] ) mymax( [42,-100,7] ) mymax( [42,7] ) mymax( [42] ) 42 base case drop 1st drop 2nd

172 Try it! def power(b,p): Handle negative values of p in an elif. """ returns b to the p power Use recursion, not ** Inputs: int b, int p: the base and the power """ Want more power? power(2,5) == 32.0 For example, power(5,-1) == 0.2 def sajak(s): sajak('wheel of fortune') == 6 What 7-letter English word w maximizes sajak(w) ? What about y? You decide… """ returns the number of vowels in the input string, s """ Want more Pat? if : if s == '': Base case test elif else: p == 0 return else: return Base case test elif in general:

173 power( 2, 5 ) 2* power( 2, 4 ) 2* 2* power( 2, 3 ) 2* 2* 2* power( 2, 2 ) 2* 2* 2* 2* power( 2, 1 ) 2* 2* 2* 2* 2* power( 2, 0 ) 2* 2* 2* 2* 2* 1 32

174 sajak( 'eerier' ) 1+ sajak( 'erier' ) 1+ 1+ sajak( 'rier' ) 1+ 1+ 0+ sajak( 'ier' ) 1+ 1+ 0+ 1+ sajak( 'er' ) 1+ 1+ 0+ 1+ 1+ sajak( 'r' ) 1+ 1+ 0+ 1+ 1+ 0+ sajak( '' ) 1+ 1+ 0+ 1+ 1+ 0+ 0 4

175 def power(b,p): """ inputs: base b and power p (an int) implements: b**p """ if p == 0: return 1.0 elif p < 0: return ____________________ else: return b * power(b,p-1) Recursion is power!

176 # of vowels in s sajak(s): Base case? When there are no letters, there are ZERO vowels if s[0] is NOT a vowel, the answer is Rec. step? Look at the initial character. if s[0] is a vowel, the answer is DESIGNDESIGN sajak( s[1:] ) 1 + sajak( s[1:] )

177 def sajak(s): if s == '': return 0 elif s[0]=='a' or s[0]=='e' or… but how to check for vowels? Is s[0] a vowel?

178 Python is… in >>> 'i' in 'team' False >>> 'cs' in 'physics' True >>> 42 in [41,42,43] True >>> 42 in [[42], '42'] False I guess Python's the in thing >>> 'i' in 'alien' True >>> 3*'i' in 'alien' False

179 def sajak(s): if len(s) == 0: return 0 elif s[0] in 'aeiou': return 1 + sajak(s[1:]) else: return 0 + sajak(s[1:]) if s[0] is NOT a vowel, the answer is just the number of vowels in the rest of s if s[0] IS a vowel, the answer is 1 + the # of vowels in the rest of s Base Case Recursive Cases let's input 'eerier' for s

180 The key to understanding recursion is, first, to understand recursion. - a former CS 5 student tutors @ LAC W/Th/F/Sa/Su Good luck with Homework #1 It's the eeriest!

181 Nature prefers recursion, too! Recursion's challenge? You need to see BOTH the self-similar pieces AND the whole thing simultaneously!

182

183 Yes... and no.Are these rules for real?

184 Dragon's-blood Tree

185 There still has to be a base case…

186 or else!


Download ppt "Cyriak: conceptually disruptive recursion… Baaa. Welcome to IST338… Be sure to watch your head!"

Similar presentations


Ads by Google