eecs 110: lec 12: mutable data aleksandar kuzmanovic northwestern university
TRANSCRIPT
EECS 110: Lec 12: Mutable Data
Aleksandar Kuzmanovic
Northwestern University
http://networks.cs.northwestern.edu/EECS110-s15/
>>> diff([7, 0, 6, 4])
1
"Quiz"Print a list of strings with
the specified format
def diff( L ):
Return the min difference between any 2 elements in L
You need determine each element's index…
Example:
Example:
You can assume at least 2 elements in the list
Only consider unsigned differences. >>> items = [“coke”, “pepsi”, “sprite”]
>>> printItems(items)0 : coke1 : pepsi2 : sprite
def printItems( items ):
Name(s):_______________________________
Hint: use a NESTED loop
"Quiz" part 1: Print Items
>>> items = [“coke”, “pepsi”, “sprite”]>>> printItems(items)0 : coke1 : pepsi2 : sprite
"Quiz" part 1: Print Items
>>> items = [“coke”, “pepsi”, “sprite”]>>> printItems(items)0 : coke1 : pepsi2 : sprite
def printItems(items): for x in range(len(items)): print(x,”:”,items[x])
"Quiz" part 1: Print Items
>>> items = [“coke”, “pepsi”, “sprite”]>>> printItems(items)0:coke1:pepsi2:sprite
def printItems(items): for x in range(len(items)): print(str(x)+”:”+items[x])
>>> diff([7, 0, 6, 4])
1
"Quiz" Part 2
def diff( L ):
Return the min difference between any 2 elements in L
Example:
You can assume at least 2 elements in the list
Only consider unsigned differences.
Hint: use a NESTED loop
>>> diff([7, 0, 6, 4])
1
"Quiz" Part 2
def diff( L ):
mindif = abs(L[1] – L[0])
for i in range(len(L)-1):
for j in range(i+1,len(L)):
d = abs(L[i]-L[j])
if d < mindiff:
mindiff = d
return mindif
Return the min difference between any 2 elements in L
Example:
You can assume at least 2 elements in the list
Only consider unsigned differences.
Hint: use a NESTED loop
EECS 110 Today
infinitely nested structure… HW 5 Preview:
Pr 1 (Lab): The Game of Life
Pr 2: Markov Text Generation
required
optional
Pr 3: ASCII Art
Pr 4: A program that reads
Pr 5: Gaussian Elimination
Mutable vs. Immutable data
Changeable types:
dictionary
Unchangeable types:
list
tuple
string
int
float
bool
Functions and (immutable) Variablesdef fact(a): result = 1 while a > 0: result *= a a -= 1 return result
>>> x = 5>>> y = fact(x)>>> x??
Functions and (immutable) Variablesdef fact(a): result = 1 while a > 0: result *= a a -= 1 return result
>>> x = 5>>> y = fact(x)>>> x5
Functions and (immutable) Variables
def swap(a, b): temp = a a = b b = temp
>>> x = 5>>> y = 10>>> swap(x, y)>>> print(x, y)??
x
y
a
b
temp
Functions and (immutable) Variables
def swap(a, b): temp = a a = b b = temp
>>> x = 5>>> y = 10>>> swap(x, y)>>> print(x, y)5, 10
x
y
a
b
temp
Functions and Mutable Types
def swap(L, i1, i2): temp = L[i1] L[i1] = L[i2] L[i2] = temp
>>> MyL = [2, 3, 4, 1]>>> swap(myL, 0, 3) >>> print(myL)??
RAM
MyL
L
i1
i2
42
43
44
45
Functions and Mutable Types
def swap(L, i1, i2): temp = L[i1] L[i1] = L[i2] L[i2] = temp
>>> MyL = [2, 3, 4, 1]>>> swap(myL, 0, 3) >>> print(myL)[1,3,4,2]
RAM
MyL
L
i1
i2
42
43
44
45
Reference vs. Value
Mutable types:
dictionary
Unmutable types:
list
tuple
string
int
float
bool
LL[0] L[1] L[2]
Reference,Pointer,
id
L = [5,42,'hi']
L5 42 'hi'
42
L = 42
“Pass By Value”
def main(): """ calls conform """ print(" Welcome to Conformity, Inc. ”)
fav = 7 conform(fav)
print(" My favorite number is", fav)
def conform(fav): """ sets input to 42 """ fav = 42 return fav
7
fav
fav
7
“Pass By Value”
def main(): """ calls conform """ print " Welcome to Conformity, Inc. "
fav = 7 conform(fav)
print " My favorite number is", fav
def conform(fav): """ sets input to 42 """ fav = 42 return fav
7
fav
fav
PASSBY
VALUE
“Pass by value” means that data is copied when sent to a method
42
Passing lists by value…
def main() """ calls conform2 """ print " Welcome to Conformity, Inc. " fav = [ 7, 11 ] conform2(fav) print " My favorite numbers are", fav
def conform2(fav) """ sets all of fav to 42 """ fav[0] = 42 fav[1] = 42
What gets passed by value here?
favL[0] L[1]
7 11
fav
Passing lists by value…
def main(): """ calls conform2 """ print " Welcome to Conformity, Inc. " fav = [ 7, 11 ] conform2(fav) print " My favorite numbers are", fav
def conform2(fav): """ sets all of fav to 42 """ fav[0] = 42 fav[1] = 42
favL[0] L[1]
7 11
fav
can change data elsewhere!
The reference is copied!
The conclusion
You can change the contents of lists in functions that take those lists as input.
Those changes will be visible everywhere.
(actually, lists or any mutable objects)
(immutable objects are safe, however)
More examples
def zeroOdd1( L ): for i in range(len(L)): if L[i] % 2 == 1: L[i] = 0
def zeroOdd2( L ): for i in L: if i % 2 == 1: i = 0
>>> L = [1, 2, 3, 4, 5]>>> zeroOdd1(L)>>> L??>>> L = [1, 2, 3, 4, 5]>>> zeroOdd2(L)>>> L
More examples
def zeroOdd1( L ): for i in range(len(L)): if L[i] % 2 == 1: L[i] = 0
def zeroOdd2( L ): for i in L: if i % 2 == 1: i = 0
>>> L = [1, 2, 3, 4, 5]>>> zeroOdd1(L)>>> L[0,2,0,4,0]>>> L = [1, 2, 3, 4, 5]>>> zeroOdd2(L)>>> L??
More examples
def zeroOdd1( L ): for i in range(len(L)): if L[i] % 2 == 1: L[i] = 0
def zeroOdd2( L ): for i in L: if i % 2 == 1: i = 0
>>> L = [1, 2, 3, 4, 5]>>> zeroOdd1(L)>>> L[0,2,0,4,0]>>> L = [1, 2, 3, 4, 5]>>> zeroOdd2(L)>>> L[1,2,3,4,5]
Lists’ flexibility
Lists can hold ANY type of data
A = [ 42., 75., 70. ] 42.0 75.0 70.0float float floatlist
A
they don’t have to be horizontal
lists!
42.0
75.0
70.0
double
double
double
listAthey don’t have
to be horizontal lists!
Lists’ flexibility
Lists can hold ANY type of data
A = [ 42., 75., 70. ] 42.0 75.0 70.0float float floatlist
A
Lists’ flexibility
Lists can hold ANY type of data
42.0 75.0 70.0double double doublelist
A
42 7 -11int int intlist
A
“go” “red” “sox!”
String String StringlistA
2d lists or arrays
Lists can hold ANY type of data -- including lists !
listA
A = [ [1,2,3,4], [5,6], [7,8,9,10,11] ]
listA
2d arrays
list
list
list
A[0]
A[1]
A[2]
Lists can hold ANY type of data -- including lists !
A = [ [1,2,3,4], [5,6], [7,8,9,10,11] ]
listA
Jagged arrays
list
list
list
A[0]
A[1]
A[2]
Lists can hold ANY type of data -- including lists !
A = [ [1,2,3,4], [5,6], [7,8,9,10,11] ]
Rows within 2d arrays need not be the same length…
listA
list
list
list
A[0]
A[1]
A[2]
Lists can hold ANY type of data -- including lists !
A = [ [1,2,3,4], [5,6], [7,8,9,10,11] ]
Rows within 2d arrays need not be the same length…
We will not use jagged arraysat least in hw 5
Rectangular arrays
Handling rectangular arrays …
listA
list
list
list
A[0]
A[1]
A[2]
How many rows does A have, in general ?
How many columns does A have, in general ?
A[2][3]
A[0][0]
Rectangular arrays
Handling rectangular arrays …
listA
list
list
list
A[0]
A[1]
A[2]
How many rows does A have, in general ?
How many columns does A have, in general ?
A[2][3]
A[0][0]
len(A)
Rectangular arrays
Handling rectangular arrays …
listA
list
list
list
A[0]
A[1]
A[2]
How many rows does A have, in general ?
How many columns does A have, in general ?
A[2][3]
A[0][0]
len(A)
len(A[0])
Which one works?
How could we create a rectangular array (of default data, 0),given its height and width ?
or
A = [ [0]*width ]*height
A = [ [0]*height ]*width
Which one works?
How could we create a rectangular array (of default data, 0), given its height and width ?
A = [ [0]*width ]*height
A = [ [0]*height ]*width
What's really going on?
A = [ [0]*width ]*height
inner = [0]*widthA = [inner]*height
Creating a 2d array
def create2dArray( width, height ): """ does just that """
A = [] # start with nothing
for row in range( height ):
for col in range( width ):
Creating a 2d array
def create2dArray( width, height ): """ does just that """
A = [] # start with nothing
for row in range( height ): A = A + [[]] for col in range( width ): A[row] = A[row] + [0] return A
"Quiz"
What are the values of A, B, C and D at the indicated points?
def mystery1(L1, L2): S = L1 for i in range(len(L2)): S[i] += L2[i] return L2
def mystery2(L1, L2): S = [0]*len(L1) for i in range(len(L2)): S[i] = L1[i] + L2[i]
>>> A = [22, 10, 30]>>> B = [20, 32, 12]>>> C = []>>> D = []>>> C = mystery1(A, B)>>> D = mystery2(A, B)
123
1)
2)
3)
Name(s)__________________________________
"Quiz"
def mystery1(L1, L2): S = L1 for i in range(len(L2)): S[i] += L2[i] return L2
def mystery2(L1, L2): S = [0]*len(L1) for i in range(len(L2)): S[i] = L1[i] + L2[i]
>>> A = [22, 10, 30]>>> B = [20, 32, 12]>>> C = []>>> D = []>>> C = mystery1(A, B)>>> D = mystery2(A, B)
123
1)
2)
3)
Name(s)__________________________________
A: [22, 10, 30]B: [20, 32, 12]C: []D: []
What are the values of A, B, C and D at the indicated points?
"Quiz"
def mystery1(L1, L2): S = L1 for i in range(len(L2)): S[i] += L2[i] return L2
def mystery2(L1, L2): S = [0]*len(L1) for i in range(len(L2)): S[i] = L1[i] + L2[i]
>>> A = [22, 10, 30]>>> B = [20, 32, 12]>>> C = []>>> D = []>>> C = mystery1(A, B)>>> D = mystery2(A, B)
123
1)
2)
3)
Name(s)__________________________________
A: [22, 10, 30]B: [20, 32, 12]C: []D: []
A: [22, 10, 30]B: [20, 32, 12]C: [20, 32, 12]D: []
What are the values of A, B, C and D at the indicated points?
"Quiz"
def mystery1(L1, L2): S = L1 for i in range(len(L2)): S[i] += L2[i] return L2
def mystery2(L1, L2): S = [0]*len(L1) for i in range(len(L2)): S[i] = L1[i] + L2[i]
>>> A = [22, 10, 30]>>> B = [20, 32, 12]>>> C = []>>> D = []>>> C = mystery1(A, B)>>> D = mystery2(A, B)
123
1)
2)
3)
Name(s)__________________________________
A: [22, 10, 30]B: [20, 32, 12]C: []D: []
A: [22, 10, 30]B: [20, 32, 12]C: [20, 32, 12]D: []
A: [22, 10, 30]B: [20, 32, 12]C: [20, 32, 12]D: None
What are the values of A, B, C and D at the indicated points?
+= mutates Mutable Data (lists)
WARNING: For mutable data types, the following are NOTthe same
A = []B = AA += [42, 42]
A = []B = AA = A + [42, 42]
NOT THE SAME!
MUTATES A(B changes too)
COPIES A(B does not change)
The Game of Life: History
• Created by John Horton Conway,a British Mathematician
• Inspired by a problem presentedby John Von Neumann:– Build a hypothetical machine that
can build copies of itself
• First presented in 1970, Scientific American
Problem 1 -- “Life”
Evolutionary rules
Grid World
• Everything depends on a cell’s eight neighbors
red cells are alive
white cells are empty
• Exactly 3 neighbors give birth to a new, live cell!
• Exactly 2 or 3 neighbors keep anexisting cell alive
• Any other number of neighbors kill the central cell (or keep it dead)
Problem 1 -- Life
Evolutionary rules
Grid World
• Everything depends on a cell’s eight neighbors
red cells are alive
white cells are empty
• Exactly 3 neighbors give birth to a new, live cell!
• Exactly 2 or 3 neighbors keep anexisting cell alive
• Any other number of neighbors kill the central cell (or keep it dead)
Problem 1 -- Life
Evolutionary rules
Grid World
• Everything depends on a cell’s eight neighbors
red cells are alive
white cells are empty
• Exactly 3 neighbors give birth to a new, live cell!
• Exactly 2 or 3 neighbors keep anexisting cell alive
• Any other number of neighbors kill the central cell (or keep it dead)
Problem 1 -- Life
Evolutionary rules
Grid World
• Everything depends on a cell’s eight neighbors
red cells are alive
white cells are empty
• Exactly 3 neighbors give birth to a new, live cell!
• Exactly 2 or 3 neighbors keep anexisting cell alive
• Any other number of neighbors kill the central cell (or keep it dead)
life out there...
Keep going!
Problem 1 -- Creating Life
0 1 2 3 4 50 1 2 3 4 5
0
1
2
3
4
5
0
1
2
3
4
5
updateNextLife(oldB, newB)
old generation or "board" new generation or "board"
Problem 1 -- Creating Life
0 1 2 3 4 50 1 2 3 4 5
0
1
2
3
4
5
0
1
2
3
4
5
old generation or "board" new generation or "board"
updateNextLife(oldB, newB)
Problem 1 -- Details
For each generation… • 0 represents an empty cell
• 1 represents a living cell
• outermost edge should always be left empty (even if there are 3 neighbors)
• compute all cells based on their previous neighbors
http://www.math.com/students/wonders/life/life.html
old generation or "board" new generation or "board"
life out there...
updateNextLife(oldB, newB)
Problem 1 – Main Loop
def life( width, height ): """ will become John Conway's Game of Life... """ B = createBoard(width, height) csplot.showAndClickInIdle(B) while True: # run forever csplot.show(B) # show current B time.sleep(0.25) # pause a bit oldB = B B = createBoard( width, height ) updateNextLife( oldB, B ) # gets a new board
Problem 1 – Main Loop
def life( width, height ): """ will become John Conway's Game of Life... """ B = createBoard(width, height) csplot.showAndClickInIdle(B) while True: # run forever csplot.show(B) # show current B time.sleep(0.25) # pause a bit oldB = B B = createBoard( width, height ) updateNextLife( oldB, B ) # gets a new board
Why not just have update RETURN a new list? (i.e., why bother with mutation at all?)
Update MUTATES the list B
Problem 1 -- to and beyond!
• Are there stable life configurations?
• Are there oscillating life configurations?
• Are there self-propagating life configurations?
"rocks"
"plants"
"animals"
period 3
period 2
Problem 1 -- to and beyond!
• Are there life configurations that expand forever?
• What is the largest amount of the life universe that can be filled with cells?
• How sophisticated can the structures in the life universe be?
http://www.ibiblio.org/lifepatterns/
• Are all feasible configurations reachable?
See you in Lab!