IS 313 Tomorrow… IS 313 Today? 9/16/09 - today: recursion and beyond! 9/23/09 - next wk: no...

Post on 05-Jan-2016

218 views 1 download

Transcript of IS 313 Tomorrow… IS 313 Today? 9/16/09 - today: recursion and beyond! 9/23/09 - next wk: no...

IS 313 Tomorrow…

IS 313 Today?

9/16/09 - today: recursion and beyond!

9/23/09 - next wk: no meeting (DC)

9/30/09 - following wk: for & while

Homework

functions moved ahead 1 week

recursion and beyond…

Choosing the right door… ?

Computation's Dual Identity

name: xtype: intLOC: 300

41

"variables as containers"

memory location 300

Computation Data Storage

name: ytype: intLOC: 304

42

memory location 304

accessed through functions…lists and strings…

Data: review…

# my own function!

def dbl( x ):

""" returns double its input, x """

return 2*x

How functions look

Comments

Docstrings

(1) describes overall what the function does, and

(2) explains what the inputs mean/are

They become part of python's built-in help system! With each function be sure

to include one that

They begin with #

keywords

def starts the functionreturn stops it

immediately and sends back the return value

Some of Python's baggage…

Look good to me!

# is it dis-0 or dis-O, anyway?

def undo(s):

""" this "undoes" its string input, s """

return 'de' + s

Functioning with strings and lists…

# what does this do?

def warp(L):

""" L can be any sequence """

return L[1:] + L[0:1]

>>> undo(undo('caf'))

>>> warp('space')

>>> warp('drake')

def chop(s):

""" mystery! """

return

Functioning with strings and lists…

def stackup(s):

""" mystery! """

return

>>> chop('graduate')'grad'

>>> chop(chop('abcd'))'a'

>>> stackup('star')'starrats'

>>> stackup('dumbmob ')'dumbmob bombmud'

# you don't need these comments

def chop(s):

""" this returns half

its string input, s """

return s[:len(s)/2]

Functioning with strings and lists…

def stackup(s):

""" this outputs the original s

with the reverse of s

tacked onto its end… """

return s + s[::-1]

>>> chop('graduate')'grad'

>>> chop(chop('abcd'))'a'

>>> stackup('star')'starrats'

>>> stackup('dumbmob ')'dumbmob bombmud'

return != print

>>> answer = dbl(21)

def dbl(x):

""" doubles x """

return 2*x

def dblPR(x):

""" doubles x """

print 2*x

>>> answer = dbl(21)

return provides the function call's value …

print just prints

Recursion warning: Be sure to watch your head!

def fac(N):

if N <= 1: return 1 else: return N * fac(N-1)

You handle the base case – the easiest possible

case to think of!

Recursion does almost all of the rest of the problem!

Exploit self-similarity

Produce short, elegant code

Less work !

Let recursion do the work for you.

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

if :

else:

base case test!

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

if s == '':

return 0

else:

rest = s[1:]

len_of_rest = mylen( rest )

total_len = 1 + len_of_rest

return total_len

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

if s == '':

return 0

else:

rest = s[1:]

len_of_rest = mylen( rest )

return 1 + len_of_rest

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

if s == '':

return 0

else:

rest = s[1:]

return 1 + mylen( rest )

Recursion Examples

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…

Recursion Examples

def mymax(L):

""" input: a NONEMPTY list, L

output: L's maximum element

"""

if :

elif :

else:

base case test!

another case…

Recursion Examples

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?!

mymax( [1,7,3,42,5] )Behind the curtain…

Recursion: not just numbers

Relationships

Self-similarity elsewhere...

Natural phenomena

Names / Acronyms

What is an “ancestor” ?

how much here is leaf vs. stem?

GNU == "GNU’s Not Unix"

Recursion: not just numbers

Relationships

Self-similarity elsewhere...

Natural phenomena

Names / Acronyms

What is an “ancestor” ?

GNU

all stem!

An ancestor is a parent OR an ancestor of a

parent…

== GNU’s Not Unix

Try it!def power(b,p):

""" returns b to the p power using recursion, not ** inputs: int b, int p output: a float"""

power(5,2) == 25.0

def sajak(s):

sajak('wheel of fortune') == 6

What seven-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 :

Base case test

elif

else:

Base case test

else:

Remember: bp == b * bp-1

def power(b,p): """ inputs: base b and power p (an int)

implements: b**p

"""

if p == 0:

return

else:

returnRecursion is

power!

behind the curtainpower(2,3)

def sajak(s):

Base case?when there are no letters,

there are ZERO vowels

if it is NOT a vowel, the answer is

Rec. step?

Look at the initial character.

if it IS a vowel, the answer is

def sajak(s):

Base case?when there are no letters,

there are ZERO vowels

if it is NOT a vowel, the answer is just the number of vowels in the rest of sRec. step?

Look at the initial character.

if it IS a vowel, the answer is 1 + the number of vowels in the rest of s

def sajak(s):

if s == '':

return 0

elif s[0]=='a' or s[0]=='e' or…

Checking for a vowel: Try #1

Base Case

def sajak(s):

if len(s) == 0:

return 0

elif s[0] in 'aeiou':

return 1 + sajak(s[1:])

else:

return sajak(s[1:])

if it is NOT a vowel, the answer is just the number of vowels in the

rest of s

if it IS a vowel, the answer is 1 + the number of vowels in the

rest of s

Base Case

Rec. Steps

sajak('eerier')behind the curtain

crazy recursion…

"List Comprehensions"

on top of recursion?

Creating general functions that will be useful everywhere (or almost…)

building blocks with which to compose…

sum, range

def sum(L):

""" input: a list of numbers, L

output: L's sum

"""

if len(L) == 0:

return 0.0

else:

return L[0] + sum(L[1:])

Base Caseif the input

has no elements, its sum is

zero

Recursive Case

if L does have an element, add

that element's value to the sum of the REST of

the list…

This input to the recursive call must be "smaller" somehow…

sum, range

def range(low,hi):

""" input: two ints, low and hi

output: int list from low up to hi

"""

if hi <= low:

return []

else:

return

what's cookin' here?

excluding hi

sum and range

>>> sum(range(1,101))

Looks sort of scruffy for a 7-year old… !

and 100 more…

http://www.americanscientist.org/template/AssetDetail/assetid/50686

1784

Recursion: Good News/Bad News

Functions are fundamental

def dblList(L):

""" Doubles all the values in a list.

input: L, a list of numbers """

if L == []:

return L

else:

return [ L[0]*2 ] + dblList(L[1:])

But the recursion can be folded away…Is this the good news or the bad

news?

recursion == function-based control!

List Comprehensions

>>> [ 2*x for x in [0,1,2,3,4,5] ][0, 2, 4, 6, 8, 10]

>>> [ y**2 for y in range(6) ][0, 1, 4, 9, 16, 25]

>>> [ c == 'A' for c in 'GTTACATT' ][0, 0, 0, 1, 0, 1, 0, 0]

What is going on here?

output

output

output

input

input

input

The same as map!

List Comprehensions

>>> [ 2*x for x in [0,1,2,3,4,5] ][0, 2, 4, 6, 8, 10]

>>> [ y**2 for y in range(6) ][0, 1, 4, 9, 16, 25]

Expression you want to happen

to each element of a

list

output

output

output

input

input

input

name that takes on the value of each element in

turnthe list (or

string)any name is OK!

Is this really the best name Guido Van Rossum

could think of?

>>> [ c == 'A' for c in 'GTTACATT' ][0, 0, 0, 1, 0, 1, 0, 0]

List Comprehensions

>>> [ 2*x for x in [0,1,2,3,4,5] ][0, 2, 4, 6, 8, 10]

>>> [ y**2 for y in range(6) ][0, 1, 4, 9, 16, 25]

output

output

output

input

input

input

name that takes on the value of each element in

turnthe list (or

string)any name is OK!

Google's Maps

One-hit wonders

Lazy lists

Expression you want to happen

to each element of a

list

>>> [ c == 'A' for c in 'GTTACATT' ][0, 0, 0, 1, 0, 1, 0, 0]

A list comprehension by any other name would be as sweet…

List Comprehensions

Use range and L.C.'s to create these data lists:

[ 0.0, 0.5, 1.0, 1.5 ]

[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ]

[ 1.0, 0.75, 0.5, 0.25, 0.0 ]

[ ]for

output List comprehension

inexpression variable name list

I don't see how this list factors in here…?

Recursion vs.

def len(L): if L == []: return 0 else: return 1 + len(L[:])

len(L)

implemented via raw recursion

A list comprehension by any other name would be as sweet…

sajak(s)def sajak(s): if len(s) == 0: return 0 else: if s[0] not in 'aeiou': return sajak(s[1:]) else: return 1+sajak(s[1:])

# of vowels

List Comprehensions

LC = [1 for x in L] return sum( LC )

len(L):

A list comprehension by any other name would be as sweet…

sajak(s):LC = [ for c in s]return sum( LC )

# of vowels

Remember True == 1 and False == 0

Write each of these functions concisely using list comprehensions…

def count(e,L):

def lotto(Y,W):

input: e, any element L, any list or stringoutput: the # of times L contains e example: count('G', 'GTCGG') == 3

input: Y and W, two lists of lottery numbers (ints)output: the # of matches between Y & W example: lotto([5,7,42,44],[3,5,7,44]) == 3

Y are your numbersW are the winning numbers

Remember True == 1 and False == 0

Extra!

def ndivs(N): input: N, an int >= 2

output: the number of positive divisors of Nexample: ndivs(12) == 6 (1,2,3,4,6,12)

LC = [ for x in L ]

return sum(LC) don't use e here!

use e in here somehow…

LC =

return sum(LC)

Quiz

def count(n,L):

input: n, any element L, any list or stringoutput: the # of times L contains n example: count('G', 'GTCGG') == 3

Remember True == 1 and False == 0

LC = [ for x in L ]return sum(LC) don't use e

here!use e in here somehow…

Write def lotto(Y,W):

input: Y and W, two lists of lottery numbers (ints)output: the # of matches between Y & W example: lotto([5,7,42,44],[3,5,7,44]) == 3

Y are your numbersW are the winning numbers

Extra! Write def divs(N):

input: N, an int >= 2output: the number of positive divisors of Nexample: divs(12) == 6 (1,2,3,4,6,12)

How could you use this to compute all of the prime

numbers up to P?

What if you want the divisors themselves?

"two-by-four landscape"

Maya Lin, Computer Scientist…

One building block, carefully applied, over 50,000 times…

Maya Lin, Computer Scientist…

A random aside…

import random

random.choice( L )

random.uniform(low,hi)

random.choice( ['north', 'case', 'west'] )

random.uniform(41.9,42.1)

chooses 1 element from the list L

chooses a random float from low to hi

for more explanation, try dir(random) or help(random)

How likely is this to return 42 ?

How would you get a random int from 0 to 9?

A random function…

print the guesses ?

return the number of guesses ?

from random import *

def guess( hidden ): """ guesses the user's hidden # """ compguess = choice( range(100) )

if compguess == hidden: # at last! print 'I got it!'

else: guess( hidden )

This is a bit suspicious…

slow down…

The final version

from random import *import time

def guess( hidden ): """ guesses the user's hidden # """ 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 )

print: Making programs talk to you!

Debugging had to be discovered. I can remember the exact instant

when I realized that a large part of my life from then on was going to be spent in finding mistakes

in my own programs.- Maurice Wilkes

Programming: the art of debugging an empty file.- The Jargon File

http://www.tuxedo.org/~esr/jargon/

The first bug

Grace Hopper

“In the days they used oxen for heavy pulling, when one ox couldn't budge a log, they didn't try to grow a larger ox. We shouldn't be trying for bigger and better computers, but for

better systems of computers.”

from the UNIVAC 1

The two Monte Carlos

Monte Carlo casino, Monaco

Making random numbers work for you!

Monte Carlo methods, Math/CS

Monte Carlo in action

def countDoubles( N ): """ inputs a # of dice rolls outputs the # of doubles """ 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 countDoubles( N-1 ) # NOT doubles else: return # doubles!

one roll

where is the doubles check?

the input N is the total number

of rolls

what should the last line be?

How many doubles will you get in N rolls of 2 dice?

Monty Hall

Let’s make a deal ’63-’86

Sept. 1990

inspiring the “Monty Hall paradox”

Monty Hall

Getting the user's input:

answer = raw_input( 'What is your name?' )

door = input( 'Which door do you choose?' )

response = raw_input( 'Switch or stay?' )

Making decisions

if response == 'switch':

print 'So you switch to door', other_door

But how to get the "other door" ?

Monte Carlo Monty Hall

Suppose you always switch to the other door...What are the chances that you will win the car ?

Run it (randomly) 1000 times and see!

Monte Carlo Monty Hall

def MCMH( init, sors, N ): """ plays the same "Let's make a deal" game, N times returns the number of times you win the car """ if N == 0: return 0 # don't play, can't win carDoor = choice([1,2,3]) # where is the car?

if init == carDoor and sors == 'stay': result = 'Car!' elif init == carDoor and sors == 'switch': result = 'Spam.' elif init != carDoor and sors == 'switch': result = 'Car!' else: result = 'Spam.'

print 'You get the', result if result == 'Car!': 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

Monty Hall

Let’s make a deal ’63-’86

Sept. 1990

inspiring the “Monty Hall paradox”

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

Base Case

Recursive Step

Thinking recursively !

Human: Base case and 1 step Computer: Everything else

Behind the curtain…

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

fac(1)

Result: 1 The base case is No Problem!

Behind the curtain…

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

fac(5)

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

fac(5)

5 * fac(4)

Behind the curtain…

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

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)

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)

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)

fac(5)

5 * fac(4)

4 * fac(3)

3 * fac(2)

2 * fac(1)

1

"The Stack"

Remembers all of the individual calls to

fac

Behind the curtain…

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

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)

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)

fac(5)

5 * fac(4)

4 * 6

Behind the curtain…

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

fac(5)

5 * 24

Behind the curtain…

def fac(N):

if N <= 1: return 1

else: return N * fac(N-1)

fac(5)

Result: 120

0 N*** -> X 1

0 x*** -> N 0Look familiar?

Base Case

Recursive Step

Behind the curtain…

One Step

But you do need to do one small step…

def fac(N):

if N <= 1: return 1 else: return fac(N)

You handle the base case – the easiest possible

case to think of!

This will not work

Breaking Up…

is easy to do with Python.

s = "this has 2 t's"

How do we get at the initial character of s?

L = [ 21, 5, 16, L ]

How do we get at the initial element of L?

How do we get at ALL THE REST of s?

How do we get at ALL the REST of L?

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

if s == '':

return

else:

return

Recursion Examples

def mylen(s):

""" input: any string, s

output: the number of characters in s

"""

if s == '':

return 0

else:

return 1 + mylen( s[1:] )

Will this work for lists?

mylen('cs5')Behind the curtain…

Recursion Examples

def mymax(L):

""" input: a NONEMPTY list, L

output: L's maximum element

"""

Recursion Examples

def mymax(L):

""" input: a NONEMPTY list, L

output: L's maximum element

"""

if len(L) == 1:

return

else:

Recursion Examples

def mymax(L):

""" input: a NONEMPTY list, L

output: L's maximum element

"""

if len(L) == 1:

return L[0]

else:

if L[0] < L[1]:

return mymax( L[1:] )

else:

return mymax( L[0:1] + L[2:] )

mymax( [1,7,3,42,5] )Behind the curtain…

Good luck with the next two Hwk problems!

The key to understanding recursion is to first

understand recursion…- advice from one of last

year's students