Upload
martina-jacobs
View
214
Download
0
Embed Size (px)
Citation preview
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
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!
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
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
Picture it!
power(2,5) -> 2*2
power(2,0) -> 1
20== 1
25
== 2*24
2p
== 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) ->
Picture it!
power(2,5) -> 2*2
power(2,0) -> 1
20== 1
25
== 2*24
2p
== 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 caseWhat should
this be?
power(b,p) ->
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
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!
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
return
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!
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
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!
# of vowels
in ssajak(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
D
E
S
I
G
N
sajak( s[1:] )
1 + sajak( s[1:] )
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?
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
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
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!
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]
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]
Empirical Hypothesis Testing…
a.k.a.
How many guesses do we expect in order to find the
correct number?
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
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'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?
[ [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's the most likely return value here?
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.
The two Monte Carlos
Monte Carlo casino, Monaco
Insights via random trials
Monte Carlo methods, Math/CS
and their denizens…
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
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?
Empirical Hypothesis Testing…
a.k.a.
How many guesses do we expect in order to find the
correct number?
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!
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!
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 theseprint DBLS[0:10]
# Let's find the average:print "av. dbls/600:", sum(DBLS)*1.0/len(DBLS)
needed a less continental name…
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]
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
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
LC
OK – got it. But what about that name?
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?
List Comprehensions?
>>> [ 2*x for x in [0,1,2,3,4,5] ][0, 2, 4, 6, 8, 10]
FunLists!Datafuncs?Google maps?
A list comprehension by any other name would be as sweet…
[ 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): ___________________________
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
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
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?
Let's make a deal: XKCD's take…
… but what if you considered the goat the grand prize!?inspiring the Monty Hall paradox
Monty
Monte Carlo Monty HallSuppose you always switch to the other door...What are the chances that you will win the prize ?
Run it (randomly) 300 times and see!
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
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 theseprint PRIZES[0:10]
# Let's find the total number of wins:how to do this… ?!
An example closer to home
......25 26 27 28 502423220
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 stake random steps starting at s until you reach either low or hi
S
An example closer to home
......25 26 27 28 502423220
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 stake random steps starting at s until you reach either low or hi
S
How could we create this
as an "ASCII" animation?
Nature prefers recursion, too!
Recursion's challenge?You need to see BOTH the self-similar pieces AND the whole thing simultaneously!
Cyriak: conceptually disruptive recursion…
is the branching, not the single-path variety.
handfingers
Python's Etch-a-Sketchthe turtle's canvas
import timefrom 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)
win
dow
_hei
ght(
)
window_width()
(42,42)
pixels!
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
def chai(size): """ mystery! """ forward(size) left(90) forward(size/2.0) right(90)
right(90) forward(size) left(90)
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!
def chai(size): """ mystery! """ if size<9: return
forward(size) left(90) forward(size/2.0) right(90)
right(90) forward(size) left(90)
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?
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?
svtree( trunkLength, levels )
svtree( 100, 5 )
levels == 5
levels == 2
levels == 0(no drawing)levels == 1
levels == 3
levels == 4
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
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!
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
The Koch curve
snowflake(100, 0) snowflake(100, 1) snowflake(100, 2)
snowflake(100, 3) snowflake(100, 4) snowflake(100, 5)
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
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
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?
>>> 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…
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…
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
output
input
input
And what if we wanted these values in red…?
[0,1,2,3]
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
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
stuff to get score…return score
letScore(c):
scrScore(s):
LC = [ letScore(c) for c in s]
return sum( LC )
def
defscrabble score!
'twelve'
Using LCs
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
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 vowelsRemember 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…
Go!Write each of these functions using list comprehensions…
def nodds(L):
def lotto(Y,W):
input: L, any list of #soutput: 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 #s W are the winning #s
def ndivs(N):
input: N, an int >= 2output: the # of positive divisors of Nexample: numdivs(12) == 6 (1,2,3,4,6,12)
LC = [ for x in L ]return sum(LC)
def primesUpTo(P):
input: P, an int >= 2output: the list of prime #s up to + incl. Pexample: primesUpTo(12) == [2,3,5,7,11] Extra!
LC = [
LC = [
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)
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 #s W are the winning #s
… could adapt to "y in Y", too.
def ndivs(N):
LC = [ for n in range(1,N+1)]
return sum(LC)
input: N, an int >= 2output: the # of positive divisors of Nexample: numdivs(12) == 6 (1,2,3,4,6,12)
def primesUpto( P ):Extra! A list of all primes up to P…
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…
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
Recursive Art ~ hw2pr4
Submit things that work …
… and even things that don't!
septagonal confetti
Cyriak's pet snake…
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)
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
20== 1
25
== 2*24
2p
== 2*2
4
power(2,p) -> 2*power(…)
Do you see the call to power!?
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 highlightsand thoughts…
Eric Nguyen
Ashraf Mathkour
Martha Parker !
11:59 !?
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 highlightsand thoughts…
Eric Nguyen
Ashraf Mathkour
Martha Parker !
11:59 !?
on-campus
tutoring!(details Wed. …)
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…
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
return
return
return
Base case test
elif
in general:
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
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
return
return
else:
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
Computation's Dual Identity
name: xtype: intLOC: 300
41
memory location 300
Computation Data Storage
name: ytype: intLOC: 304
42
memory location 304
Last time
variables ~ boxes
But what does all this stuff look like ?
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!
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…
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')print "flipside('carpets') ~", flipside('carpets') print "flipside('carpets') ~", flipside('carpets') print "flipside('carpets') ~", flipside('carpets') print "flipside('carpets') ~", flipside('carpets')
(1) function definition
(2) function tests
We provide these tests (for now…)
but don't test like this!
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…
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)
Computation's Dual Identity
name: xtype: intLOC: 300
41
memory location 300
Computation Data Storage
name: ytype: intLOC: 304
42
memory location 304
variables ~ boxes
accessed through functions…
Functions!
It's no coincidence this starts with fun!
Functioning across disciplines
def g(x): return x**100 g(x) = x
100
CS's googolizer Math's googolizerdefined by what it does defined by what it is
+ how efficiently it works
procedure structure
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
How functions work…
def f(x): return 11*g(x) + g(x/2)
>>> demo(-4) ?
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
def g(x): return -1 * x
Hey! This must be a stack-frame frame!
stack frame
def f(x): return 11*g(x) + g(x/2)
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11*g(x) + g(x/2)def g(x): return -1 * x
>>> demo(-4) ?
How functions work…
stack frame
stack frame
def f(x): return 11*g(x) + g(x/2)
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -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
stack frame
def f(x): return 11*g(x) + g(x/2)
def demo(x): return x + f(x)
demox = -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
stack frame
stack frame
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
def demo(x): return x + f(x)
demox = -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
stack frame
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11* 4 + g(-4/2)
>>> demo(-4) ?
How functions work…
the "return value"
stack frame
stack frame
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
def demo(x): return x + f(x)
demox = -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
stack frame
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11* 4 + 2
>>> demo(-4) ?
How functions work…
the "return value"
stack frame
stack frame
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11* 4 + 2 46
>>> demo(-4) ?
How functions work…
stack frame
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
def demo(x): return x + f(x)
demox = -4
return -4 + 46
42>>> demo(-4) 42
How functions work…
stack frame
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)
demox = -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
return > print
>>> ans = dbl(21)
def dbl(x): """ dbls x? """ return 2*x
def dblPR(x): """ dbls x? """ print 2*x
>>> ans = dblPR(21)
>>> 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
Thinking sequentially
5 ! = 5 * 4 * 3 * 2 * 1
N ! = N * (N-1) * (N-2) * … * 3 * 2 * 1
factorial
5 ! = 120
factorial
5 ! = 5 * 4 * 3 * 2 * 1
N ! = N * (N-1) * (N-2) * … * 3 * 2 * 1
5 ! = 120
March + beyond…
Thinking sequentially
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
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
def fac(N): return fac(N)
Roadsigns and recursionexamples of self-fulfilling danger
This runs ~ but does not help!
Recursion's advantage: It handles arbitrary structural depth – all
at once!
As a hat, I'm recursive, too!
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:
def fac(N):
if N <= 1: return 1
else: return N*fac(N-1)
Recursive case
(shorter)
Human: Base case and 1 step Computer: Everything else
Base case
Thinking recursively
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 step Computer: Everything else
Base case
Thinking recursively
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 …
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…
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 *
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 *
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 *
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 *
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 *
fac(5)
Result: 120
0 x*** -> N 0
0 N*** -> X 1Look familiar?
Recursive step
Base case
show facWPR …
Behind the curtain…
def fac(N):
if N <= 1: return 1
else: return N * fac(N-1)
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 codeLess work !
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 !
Nature prefers recursion, too!
Recursion's challenge?You need to see BOTH the self-similar pieces AND the whole thing simultaneously!
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
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 ]
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
return
… 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!
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
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
return
return
else:
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
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
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
return
return
return
Base case test
elif
in general:
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
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
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!
# of vowels
in ssajak(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
D
E
S
I
G
N
sajak( s[1:] )
1 + sajak( s[1:] )
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?
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
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
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!
Nature prefers recursion, too!
Recursion's challenge?You need to see BOTH the self-similar pieces AND the whole thing simultaneously!