Upload
josephine-harrell
View
219
Download
0
Embed Size (px)
Citation preview
EECS 110: Lec 4: Functions and Recursion
Aleksandar Kuzmanovic
Northwestern University
http://networks.cs.northwestern.edu/EECS110-s15/
Raising and razing lists
What are
"Quiz"pi = [3,1,4,1,5,9] Q = [ 'pi', "isn't", [4,2] ]
What slice of pi is [3,4,5]
What is pi[pi[2]]?
message = 'You need parentheses for chemistry !'
What is message[::5]
What are
pi[0] * (pi[1] + pi[2])
and
pi[0] * (pi[1:2] + pi[2:3])
What is message[9:15]
What are
What slice of pi is [3,1,4]
How many nested pi's before pi[…pi[0]…] produces an error?
Name(s):
Extra! Mind Muddlers
Part 2Part 1Q[0]
Q[0:1]
Q[0][1]
Q[1][0]
len(pi)
len(Q)
len(Q[1])
Raising and razing lists
What are
"Quiz"pi = [3,1,4,1,5,9] Q = [ 'pi', "isn't", [4,2] ]
What slice of pi is [3,4,5]
What is pi[pi[2]]?
message = 'You need parentheses for chemistry !'
What is message[::5]
What are
pi[0] * (pi[1] + pi[2])
and
pi[0] * (pi[1:2] + pi[2:3])
What is message[9:15]
What are
What slice of pi is [3,1,4]
How many nested pi's before pi[…pi[0]…] produces an error?
Name(s):
Extra! Mind Muddlers
Part 2Part 1Q[0]
Q[0:1]
Q[0][1]
Q[1][0]
len(pi)
len(Q)
len(Q[1])
>>> 3*'i' in 'alien'
False
The in thing
>>> 'i' in 'team'
False
>>> 'cs' in 'physics'
True
>>> ‘sleep' not in ‘EECS 110'
True
>>> 42 in [41,42,43]
True
>>> 42 in [ [42], '42' ]
False
a little bit different for lists…
Functioning in Python
Some basic, built-in functions:
abs
max
min
sum
range
round
bool
float
int
long
list
str
these change data from one type to another
absolute value
of lists
creates lists
only as accurately as it can!
helpThe most important: dir
Far more are available in separate files, or modules:
import math
math.sqrt( 1764 )
dir(math)
from math import *
pi
sin( pi/2 )
accesses math.py's functions
lists all of math.py's functions
same, but without typing math. all of the time…
Functioning in Python
# my own function!
def dbl( x ):
""" returns double its input, x """
return 2*x
Functioning in Python
# my own function!
def dbl( x ):
""" returns double its input, x """
return 2*x
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…
Functioning in Python
>>> undo('caf')
>>> undo(undo('caf'))
def undo(s):
""" this "undoes" its string input, s """
return 'de' + s
Functioning in Python
Conditional Statements
ax**2 + bx + c = 0
If b**2 – 4*a*c is equal to 0, then the equation has 1 solution
If b**2 – 4*a*c is less than 0, then the equation has no solution
If b**2 – 4*a*c is greater than 0, then the equation has 2 solutions
Striving for simplicity…
def qroots(a,b,c): """ qroots(a,b,c) returns a list of the real-number solutions to the quadratic equation ax**2 + bx + c = 0 input a: a number (int or float) input b: a number (int or float) input c: a number (int or float) """ if b**2 - 4*a*c < 0: return [ ]
if b**2 - 4*a*c == 0: return [-b/(2*a)]
else: return [(-b-(b**2 - 4*a*c)**0.5)/(2*a), (-b+(b**2 - 4*a*c)**0.5)/(2*a)]
# If b**2 – 4*a*c is less than 0# then the equation has no solution
# If b**2 – 4*a*c is equal to 0# then the equation has one solution
# Otherwise, the equation has 2 solutions
Naming data == Saving time
def qroots(a,b,c): """ qroots(a,b,c) returns a lost of the real-number solutions to the quadratic equation ax**2 + bx + c = 0 input a: a number (int or float) input b: a number (int or float) input c: a number (int or float) """ d = b**2 - 4*a*c if d < 0: return [ ]
if d == 0: return [ -b/(2*a) ]
r1 = (-b + d**0.5)/(2*a) r2 = (-b - d**0.5)/(2*a)
if r1 > r2: return [ r2, r1 ] else: return [ r1, r2 ]
Simpler to fix, if needed!
Faster to run, as well…
Naming data == Saving time
def qroots(a,b,c): """ qroots(a,b,c) returns a lost of the real-number solutions to the quadratic equation ax**2 + bx + c = 0 input a: a number (int or float) input b: a number (int or float) input c: a number (int or float) """ d = b**2 - 4*a*c if d < 0: return [ ]
if d == 0: return [ -b/(2*a) ]
r1 = (-b + d**0.5)/(2*a) r2 = (-b - d**0.5)/(2*a)
if r1 > r2: return [ r2, r1 ] else: return [ r1, r2 ]
Simpler to fix, if needed!
Faster to run, as well…
Name once - use often!
# data gets named on the way IN to a function
def qroots(a,b,c): """ qroots(a,b,c) returns a lost of roots to the quadratic equation ax**2 + bx + c = 0 input a: a number (int or float) input b: a number (int or float) input c: a number (int or float) """ d = b**2 - 4*a*c if d < 0: return [ ]
if d == 0: return [ -b/(2*a) ]
r1 = (-b + d**0.5)/(2*a) r2 = (-b - d**0.5)/(2*a)
if r1 > r2: return [ r2, r1 ] else: return [ r1, r2 ]
# notice that we don't get to name data on the way out…
Functioning Python…
Indenting indicates
code "blocks"
qroots "block" is
11 lines
Docstrings become part of python's help
system
function defs must be at the
very left
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
How functions work…
def f(x): return 11*g(x) + g(x/2)
What is demo(-4) ?
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
def g(x): return -1 * x
How functions work…
def f(x): return 11*g(x) + g(x/2)
What is demo(-4) ?
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
How functions work…
def f(x): return 11*g(x) + g(x/2)
What is demo(-4) ?
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
These are different x's !
How functions work…
def f(x): return 11*g(x) + g(x/2)
What is demo(-4) ?
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
How functions work…
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
What is demo(-4) ?
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
How functions work…
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1.0 * x
What is demo(-4) ?
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11* 4 + g(-4/2)
How functions work…
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1 * x
What is demo(-4) ?
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
How functions work…
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1.0 * x
What is demo(-4) ?
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11* 4 + 2
How functions work…
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1.0 * x
What is demo(-4) ?
def demo(x): return x + f(x)
demox = -4
return -4 + f(-4)
fx = -4
return 11* 4 + 2 46
How functions work…
def f(x): return 11*g(x) + g(x/2)
def g(x): return -1.0 * x
What is demo(-4) ?
def demo(x): return x + f(x)
demox = -4
return -4 + 46
42
Thinking sequentially
5! = 5 * 4 * 3 * 2 * 1
N! = N * (N-1) * (N-2) * … * 3 * 2 * 1
factorial
5! = 120
Recursion == self-reference!
Thinking recursively
5! = 5 * 4 * 3 * 2 * 1
N! = N * (N-1) * (N-2) * … * 3 * 2 * 1
factorial
5! = 120
N! = N * (N-1)!
Warning
def fac(N): return N * fac(N-1)
This is legal code!
def fac(N): return N * fac(N-1)
No base case -- the calls to factorial will never stop!
Make sure you have a base case, then worry about the recursive
step...
Warning
def fac(N):
if N <= 1: return 1
Thinking recursively !
Base Case
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…
Recursion Mantra
Let recursion do the work for you.
Recursion Mantra
Let recursion do the work for you.Exploit self-similarity
Produce short, elegant codeLess work !
Recursion Mantra
Let recursion do the work for you.
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 codeLess work !
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, 7 ]
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?
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, 7 ]
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?
s[0]
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, 7 ]
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?
s[0]
s[1:]
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, 7 ]
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?
s[0]
s[1:]
L[0]
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, 7 ]
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?
s[0]
s[1:]
L[0]
L[1:]
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(‘eecs')Behind the curtain…
mylen(‘eecs')Behind the curtain…
1 + mylen('ecs')
mylen(‘eecs')Behind the curtain…
1 + mylen('ecs')
1 + mylen('cs')
mylen(‘eecs')Behind the curtain…
1 + mylen('ecs')
1 + mylen('cs')
1 + mylen('s')
mylen(‘eecs')Behind the curtain…
1 + mylen('ecs')
1 + mylen('cs')
1 + mylen('s')
1 + mylen('')
mylen(‘eecs')Behind the curtain…
1 + mylen('ecs')
1 + mylen('cs')
1 + mylen('s')
1 + mylen('')
= 0
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…
"Quiz" on recursion
def power(b,p):
Names:
Handle negative values of p, as well.
""" returns b to the p power using recursion, not ** inputs: ints b and p output: a float"""
Want more power?
power(5,2) == 25.0
For example, power(5,-1) == 0.2 (or so)
def sajak(s):
sajak('wheel of fortune') == 6
""" returns the number of vowels in the input string, s"""
def power(b,p): """ inputs: base b and power p (an int)
implements: b**p = b*b**(p-1)
"""
if p == 0:
return
if p > 0:
return
else:
# p < 0
return
def power(b,p): """ inputs: base b and power p (an int)
implements: b**p = b*b**(p-1)
"""
if p == 0:
return 1
if p > 0:
return
else:
# p < 0
return
def power(b,p): """ inputs: base b and power p (an int)
implements: b**p = b*b**(p-1)
"""
if p == 0:
return 1
if p > 0:
return b*power(b,p-1)
else:
# p < 0
return
def power(b,p): """ inputs: base b and power p (an int)
implements: b**p = b*b**(p-1)
"""
if p == 0:
return 1
if p > 0:
return b*power(b,p-1)
else:
# p < 0
return 1/power(b,-1*p)
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 len(s) == 0:
return 0
else:
Checking for a vowel: Try #1
Base Case
def sajak(s):
if len(s) == 0:
return 0
else:
Checking for a vowel: Try #1
and
or
not
same as in English! but each side has to be a complete boolean value!
Base Case
def sajak(s):
if len(s) == 0:
return 0
else:
Checking for a vowel: Try #1
and
or
not
same as in English! but each side has to be a complete boolean value!
if s[0] == 'a' or s[0] == 'e' or…
Base Case
inChecking for a vowel: Try #2
def sajak(s):
if len(s) == 0:
return 0
else:
Base Case
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:])
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. Step
sajak('eerier')behind the curtain
Good luck with Homework #1
The key to understanding recursion is to first
understand recursion…- advice from a student