EECS 110 Lec 17 Review for the Final

  • Slides: 75
Download presentation
EECS 110: Lec 17: Review for the Final Exam Aleksandar Kuzmanovic Northwestern University http:

EECS 110: Lec 17: Review for the Final Exam Aleksandar Kuzmanovic Northwestern University http: //networks. cs. northwestern. edu/EECS 110 -s 18/

General Info Wednesday, June 6, 9: 30 -11: 30 am, Frances Searle Building 1

General Info Wednesday, June 6, 9: 30 -11: 30 am, Frances Searle Building 1 -441 To be done individually Closed book One 8. 5” by 11” sheet of paper permitted Please do not discuss the exam with others until everyone has taken it. There are six questions. Each question is worth 20 points. Hence, you can acquire 120 points in total. Those who get > 90 points will get an A. Those who get >80 points and <90 points will get a B, etc. 2

Final Exam 6 questions: 1. Misc 2. Loops and recursion 3. Mutation 4. 2

Final Exam 6 questions: 1. Misc 2. Loops and recursion 3. Mutation 4. 2 D in Python 5. Dictionaries 6. Classes and Objects 3

Q 2 (and Q 1): Loops (while and for) and Recursion What does this

Q 2 (and Q 1): Loops (while and for) and Recursion What does this code do? print('It keeps on') while True: print('going and') print('Phew! I'm done!’)

Extreme Looping Anatomy of a while loop: print('It keeps on') “while” loop the loop

Extreme Looping Anatomy of a while loop: print('It keeps on') “while” loop the loop keeps on running as long as this test is True while True: print('going and') print('Phew! I'm done!') This won't print until the while loop finishes in this case, never!

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) ? ? n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 7 ? ?

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 7 3

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) 7 n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 3 10

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) 7 n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 3 10 5

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) 7 n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 3 10 5 16

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) 7 n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 3 10 5 16 8

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) 7 n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 3 10 5 16 8 4

What do these two loops print? n = 0 for c in 'forty-two': if

What do these two loops print? n = 0 for c in 'forty-two': if c not in 'aeiou': n += 1 print(n) 7 n = 3 while n > 1: print(n) if n%2 == 0: n = n/2 else: n = 3*n + 1 3 10 5 16 8 4 2

fore! 1 x is assigned each value from this sequence for x in range(8):

fore! 1 x is assigned each value from this sequence for x in range(8): print('x is', x) 2 the BODY or BLOCK of the for loop runs with that x print('Phew!') 4 Code AFTER the loop will not run until the loop is finished. 3 LOOP back to step 1 for EACH value in the list

Two kinds of for loops Element-based Loops Index-based Loops sum = 0 for x

Two kinds of for loops Element-based Loops Index-based Loops sum = 0 for x in L: sum += x for i in range(len(L)): sum += L[i] i L = [ 42, -10, 4 ] x 0 1 2 L = [ 42, -10, 4 ] L[i]

Q 2: Recursion vs. Loops Solve a problem using: (a) recursion (b) loops

Q 2: Recursion vs. Loops Solve a problem using: (a) recursion (b) loops

Example 1 a: fac(N) with recursion Let recursion do the work for you. Exploit

Example 1 a: fac(N) with recursion Let recursion do the work for you. Exploit self-similarity Produce short, elegant code Less work ! def fac(N): You handle the base case – the easiest possible case to think of! if N <= 1: return 1 Recursion does almost all of the rest of the problem! else: return N * fac(N-1)

Example 1 b: fac with for (v 1) def fact( n ): answer =

Example 1 b: fac with for (v 1) def fact( n ): answer = 1 for x in range(n): answer = answer * x return answer

Example 1 b: fac with for (v 2) def fact( n ): answer =

Example 1 b: fac with for (v 2) def fact( n ): answer = 1 for x in range(1, n+1): answer = answer * x return answer

Example 2 a: sum(L) with recursion def sum(L): """ input: a list of numbers,

Example 2 a: sum(L) with recursion def sum(L): """ input: a list of numbers, L output: L's sum Base Case """ if the input has no elements, its sum is zero if len(L) == 0: This input to the recursive call must be "smaller" somehow… return 0. 0 else: return L[0] + sum(L[1: ]) Recursive Case if L does have an element, add that element's value to the sum of the REST of the list…

Example 2 b: sum(L) with for Finding the sum of a list: def sum(

Example 2 b: sum(L) with for Finding the sum of a list: def sum( L ): """ returns the sum of L's elements """ sum = 0 for x in L: sum = sum + x return sum Accumulator!

Example 3: uniquify(L) Problem: Part A Use loops (no recursion!) to write a Python

Example 3: uniquify(L) Problem: Part A Use loops (no recursion!) to write a Python function uniquify(L), which takes in any list L and returns a list of the distinct elements in the list L. The order of the elements may be preserved, but they do not have to be. For example, >>> uniquify( [ 42, 'spam', 42, 5, 5, 5 ] ) [ 'spam', 42, 5 ] >>> L = range(4) + range(3) >>> uniquify(L) [ 3, 0, 1, 2 ]

Example 3 a: uniquify(L) def uniquify(L): s = [] for i in range(len(L)): n=0

Example 3 a: uniquify(L) def uniquify(L): s = [] for i in range(len(L)): n=0 for j in range(i+1, len(L)): if L[i] == L[j]: n=1 if n == 0: s=s+[L[i]] return s

Example 3: uniquify(L) Problem: Part B Use recursion (no loops!) to write a Python

Example 3: uniquify(L) Problem: Part B Use recursion (no loops!) to write a Python function uniquify(L), which takes in any list L and returns a list of the distinct elements in the list L. The order of the elements may be preserved, but they do not have to be. For example, >>> uniquify( [ 42, 'spam', 42, 5, 5, 5 ] ) [ 'spam', 42, 5 ]

Example 3 b: uniquify(L) def uniquify(L): if len(L) == 0: return [] else: if

Example 3 b: uniquify(L) def uniquify(L): if len(L) == 0: return [] else: if L[0] in L[1: ]: return uniquify(L[1: ]) else: return L[0: 1] + uniquify(L[1: ])

Question 3: Mutation Mutable vs. Changeable types: dictionary list Immutable data Unchangeable types: tuple

Question 3: Mutation Mutable vs. Changeable types: dictionary list Immutable data Unchangeable types: tuple string int float bool

Functions and (immutable) Variables def fact(a): result = 1 while a > 0: result

Functions and (immutable) Variables def fact(a): result = 1 while a > 0: result *= a a -= 1 return result >>> x = 5 >>> y = fact(x) >>> x ? ?

Functions and (immutable) Variables def fact(a): result = 1 while a > 0: result

Functions and (immutable) Variables def fact(a): result = 1 while a > 0: result *= a a -= 1 return result >>> x = 5 >>> y = fact(x) >>> x 5

Functions and (immutable) Variables def swap(a, b): temp = a a = b b

Functions and (immutable) Variables def swap(a, b): temp = a a = b b = temp x >>> >>> ? ? a x = 5 y = 10 swap(x, y) print(x, y) y b temp

Functions and (immutable) Variables def swap(a, b): temp = a a = b b

Functions and (immutable) Variables def swap(a, b): temp = a a = b b = temp x >>> x = 5 >>> y = 10 >>> swap(x, y) >>> print(x, y) 5, 10 a y b temp

Functions and Mutable Types My. L def swap(L, i 1, i 2): temp =

Functions and Mutable Types My. L def swap(L, i 1, i 2): temp = L[i 1] = L[i 2] = temp >>> My. L = [2, 3, 4, 1] >>> swap(my. L, 0, 3) >>> print(my. L) ? ? L i 1 i 2 RAM 42 43 44 45

Functions and Mutable Types My. L def swap(L, i 1, i 2): temp =

Functions and Mutable Types My. L def swap(L, i 1, i 2): temp = L[i 1] = L[i 2] = temp >>> My. L = [2, 3, 4, 1] >>> swap(my. L, 0, 3) >>> print(my. L) [1, 3, 4, 2] L i 1 i 2 RAM 42 43 44 45

The conclusion You can change the contents of lists in functions that take those

The conclusion You can change the contents of lists in functions that take those lists as input. (actually, lists or any mutable objects) Those changes will be visible everywhere. (immutable objects are safe, however)

Example 1 def zero. Odd 1( L ): for i in range(len(L)): if L[i]

Example 1 def zero. Odd 1( L ): for i in range(len(L)): if L[i] % 2 == 1: L[i] = 0 def zero. Odd 2( L ): for i in L: if i % 2 == 1: i = 0 >>> >>> ? ? >>> >>> L = [1, 2, 3, 4, 5] zero. Odd 1(L) L L = [1, 2, 3, 4, 5] zero. Odd 2(L) L

Example 1 def zero. Odd 1( L ): for i in range(len(L)): if L[i]

Example 1 def zero. Odd 1( L ): for i in range(len(L)): if L[i] % 2 == 1: L[i] = 0 def zero. Odd 2( L ): for i in L: if i % 2 == 1: i = 0 >>> L = [1, 2, 3, 4, 5] >>> zero. Odd 1(L) >>> L [0, 2, 0, 4, 0] >>> L = [1, 2, 3, 4, 5] >>> zero. Odd 2(L) >>> L ? ?

Example 1 def zero. Odd 1( L ): for i in range(len(L)): if L[i]

Example 1 def zero. Odd 1( L ): for i in range(len(L)): if L[i] % 2 == 1: L[i] = 0 def zero. Odd 2( L ): for i in L: if i % 2 == 1: i = 0 >>> L = [1, 2, 3, 4, 5] >>> zero. Odd 1(L) >>> L [0, 2, 0, 4, 0] >>> L = [1, 2, 3, 4, 5] >>> zero. Odd 2(L) >>> L [1, 2, 3, 4, 5]

Example 2 What are the values of A, B, C and D at the

Example 2 What are the values of A, B, C and D at the indicated points? def mystery 1(L 1, N, C): for i in L 1: if i == N: C += 1 return C def mystery 2(C): for i in range(len(C)): C[i] *= 2 1 2 >>> >>> >>> A = [22, 10, 30] B = 22 C = 0 D = mystery 1(A, B, C) mystery 2(A) 1) 2)

Example 2 What are the values of A, B, C and D at the

Example 2 What are the values of A, B, C and D at the indicated points? def mystery 1(L 1, N, C): for i in L 1: if i == N: C += 1 return C def mystery 2(C): for i in range(len(C)): C[i] *= 2 1 2 >>> >>> >>> A = [22, 10, 30] B = 22 C = 0 D = mystery 1(A, B, C) mystery 2(A) A 1) 2) A B C D = = [22, 10, 30] 22 0 1

Example 2 What are the values of A, B, C and D at the

Example 2 What are the values of A, B, C and D at the indicated points? def mystery 1(L 1, N, C): for i in L 1: if i == N: C += 1 return C def mystery 2(C): for i in range(len(C)): C[i] *= 2 1 2 >>> >>> >>> A = [22, 10, 30] B = 22 C = 0 D = mystery 1(A, B, C) mystery 2(A) A 1) 2) A B C D = = [22, 10, 30] 22 0 1 A = [44, 20, 60]

Example 3: avoiding mutation Problem: Write function x(L), …. , The list L should

Example 3: avoiding mutation Problem: Write function x(L), …. , The list L should NOT mutate, i. e. , it should stay the same.

Example 3: avoiding mutation def x(L): # some function … L 2=copy. List(L) …

Example 3: avoiding mutation def x(L): # some function … L 2=copy. List(L) … # manipulate L 2, not L def copy. List(L): L 2 = [] for x in L: L 2 += [x] return L 2

Question 4: 2 D in Python Handling rectangular arrays … list A[0][0] list A[1]

Question 4: 2 D in Python Handling rectangular arrays … list A[0][0] list A[1] list A[2][3] How many rows does A have, in general ? How many columns does A have, in general ?

Rectangular arrays Handling rectangular arrays … list A[0][0] list A[1] list A[2][3] How many

Rectangular arrays Handling rectangular arrays … list A[0][0] list A[1] list A[2][3] How many rows does A have, in general ? How many columns does A have, in general ? len(A)

Rectangular arrays Handling rectangular arrays … list A[0][0] list A[1] list A[2][3] How many

Rectangular arrays Handling rectangular arrays … list A[0][0] list A[1] list A[2][3] How many rows does A have, in general ? How many columns does A have, in general ? len(A) len(A[0])

Which one works? How could we create a rectangular array (of default data, 0),

Which one works? How could we create a rectangular array (of default data, 0), given its height and width ? A = [ [0]*width ]*height or A = [ [0]*height ]*width

Which one works? How could we create a rectangular array (of default data, 0),

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]*width A =

What's really going on? A = [ [0]*width ]*height inner = [0]*width A = [inner]*height

Creating a 2 d array def create 2 d. Array( width, height ): """

Creating a 2 d array def create 2 d. Array( width, height ): """ does just that """ A = [] # start with nothing for row in range( height ): for col in range( width ):

Creating a 2 d array def create 2 d. Array( width, height ): """

Creating a 2 d array def create 2 d. Array( 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

Example 1: What 2 d loops would create a checkerboard image? def checkerboard(): #

Example 1: What 2 d loops would create a checkerboard image? def checkerboard(): # loop over each pixel for col in range(width): for row in range(height):

Example 1: What 2 d loops would create a checkerboard image? def checkerboard(): #

Example 1: What 2 d loops would create a checkerboard image? def checkerboard(): # loop over each pixel for col in range(width): for row in range(height): if (col//20 + row//20)%2 == 0: image. plot. Point( col, row )

Example 2: Write a function that returns the number of all-zero rows

Example 2: Write a function that returns the number of all-zero rows

Example 2: Write a function that returns the number of all-zero rows def num_zero_rows(L):

Example 2: Write a function that returns the number of all-zero rows def num_zero_rows(L): width = len(L[0]) height = len(L) n = 0 for row in range(height): k = 0 for col in range(width): if L[row][col] != 0: k = 1 if k == 0: n += 1 return n

Question 5: Dictionaries In Python a dictionary is a set of key - value

Question 5: Dictionaries In Python a dictionary is a set of key - value pairs. >>> d = {} >>> d[1988] = 'dragon' >>> d[1989] = 'snake' >>> d {1988: 'dragon', 1989: 'snake'} >>> d[1988] 'dragon' >>> d[1987] key error It's a list where the index can be any immutable-type key.

Lists vs. Dictionaries In Python a dictionary is a set of key - value

Lists vs. Dictionaries In Python a dictionary is a set of key - value pairs. >>> d = {} creates an empty dictionary, d 1988 is the key 'dragon' is the value >>> d[1988] = 'dragon' >>> d[1989] = 'snake' 1989 is the key 'snake' is the value >>> d {1988: 'dragon', 1989: 'snake'} >>> d[1988] Anyone seen this before? Retrieve data as with lists… 'dragon' >>> d[1987] key error or almost ! It's a list where the index can be any immutable-type key.

More on dictionaries Dictionaries have lots of built-in methods: >>> d = {1988: 'dragon',

More on dictionaries Dictionaries have lots of built-in methods: >>> d = {1988: 'dragon', 1989: 'snake'} >>> d. keys() get all keys [ 1989, 1988 ] >>> 1988 in d True check if a key is present >>> 1969 in d False >>> d. pop( 1988 ) 'dragon' delete a key (and its value)

A family dictionary?

A family dictionary?

A family dictionary… T = {'abe' : ['homer', 'herb'], 'jackie': ['marge', 'patty', 'selma'], 'homer'

A family dictionary… T = {'abe' : ['homer', 'herb'], 'jackie': ['marge', 'patty', 'selma'], 'homer' : ['hugo', 'bart', 'lisa', 'maggie'], 'marge' : ['hugo', 'bart', 'lisa', 'maggie']} keys can be any immutable type T['abe'] How to get 'selma' from T? values can be any type at all…

A family dictionary… T = {'abe' : ['homer', 'herb'], 'jackie': ['marge', 'patty', 'selma'], 'homer'

A family dictionary… T = {'abe' : ['homer', 'herb'], 'jackie': ['marge', 'patty', 'selma'], 'homer' : ['hugo', 'bart', 'lisa', 'maggie'], 'marge' : ['hugo', 'bart', 'lisa', 'maggie']} keys can be any immutable type T['abe'] How to get 'selma' from T? values can be any type at all… ['homer', 'herb']

A family dictionary… T = {'abe' : ['homer', 'herb'], 'jackie': ['marge', 'patty', 'selma'], 'homer'

A family dictionary… T = {'abe' : ['homer', 'herb'], 'jackie': ['marge', 'patty', 'selma'], 'homer' : ['hugo', 'bart', 'lisa', 'maggie'], 'marge' : ['hugo', 'bart', 'lisa', 'maggie']} keys can be any immutable type T['abe'] How to get 'selma' from T? values can be any type at all… ['homer', 'herb'] T['jackie'][2] (T['jackie'] is a list)

Example 1: fav. Child def fav. Child( person, Tree ): """ person is a

Example 1: fav. Child def fav. Child( person, Tree ): """ person is a name (a string) Tree is a dictionary of children returns person's favorite child """ if person in Tree: Kids = Tree[person] Kids. sort() return Kids[0] else: return 'no children' Who is favored ? Side effects ?

Example 2: add. Child For example, >>> add. Child( 'lisa', T, 'abejr' ) def

Example 2: add. Child For example, >>> add. Child( 'lisa', T, 'abejr' ) def add. Child( person, Tree, jr ): """ adds person's new child to Tree ""“

Example 2: add. Child For example, >>> add. Child( 'lisa', T, 'abejr' ) def

Example 2: add. Child For example, >>> add. Child( 'lisa', T, 'abejr' ) def add. Child( person, Tree, jr ): """ adds person's new child to Tree ""“ if person in Tree: kids = Tree[person] kids += [jr]

EXAMPLE 3: Based on fav. Child, write fav. GChild to return the first grandchild

EXAMPLE 3: Based on fav. Child, write fav. GChild to return the first grandchild alphabetically - or return 'no one' if there are none. def fav. Child( person, Tree ): if person in Tree: Kids = Tree[person] Kids. sort() return Kids[0] else: return 'no children'

EXAMPLE 3: Based on fav. Child, write fav. GChild to return the first grandchild

EXAMPLE 3: Based on fav. Child, write fav. GChild to return the first grandchild alphabetically - or return 'no one' if there are none. def fav. Child( person, Tree ): if person in Tree: Kids = Tree[person] Kids. sort() return Kids[0] else: return 'no children' def fav. GChild( person, Tree ): g. Children = [] if person in Tree : for child in Tree[person]: if child in Tree: g. Children += Tree[child] if g. Children == []: return 'no one' else: g. Children. sort() return g. Children[0]

Question 6: Classes and Objects An object-oriented programming language allows you to build your

Question 6: Classes and Objects An object-oriented programming language allows you to build your own customized types of variables. (1) A class is a type of variable. (2) An object is one such variable. There will typically be MANY objects of a single class.

Objects An object is a data structure (like a list), except (1) Its data

Objects An object is a data structure (like a list), except (1) Its data elements have names chosen by the programmer. (2) Data elements are chosen & organized by the programmer (3) An object can have behaviors built-in by the programmer.

Objects An object is a data structure (like a list), except (1) Its data

Objects An object is a data structure (like a list), except (1) Its data elements have names chosen by the programmer. (2) Data elements are chosen & organized by the programmer (3) An object can have behaviors built-in by the programmer. usually called "methods" instead of functions

class Date: """ a blueprint (class) for objects that represent calendar days """ def

class Date: """ a blueprint (class) for objects that represent calendar days """ def __init__( self, mo, dy, yr ): """ the Date constructor """ self. month = mo self. day = dy self. year = yr The Date class def __repr__( self ): """ used for printing Dates """ s = "%02 d/%04 d" % (self. month, self. day, self. year) return s

The Date Class >>> d = Date(1, 1, 2017) this is a CONSTRUCTOR …

The Date Class >>> d = Date(1, 1, 2017) this is a CONSTRUCTOR … >>> d 1/1/2017 this is an object of type Date the representation of a particular object of type Date

class Date: More Date def __init__( self, mo, dy, yr ): def __repr__(self): def

class Date: More Date def __init__( self, mo, dy, yr ): def __repr__(self): def is. Leap. Year(self): def copy(self): """ returns a DIFFERENT object w/SAME date! """ def equals(self, d 2): """ returns True if they represent the same date; False otherwise """

class Date: More Date def __init__( self, mo, dy, yr ): def __repr__(self): def

class Date: More Date def __init__( self, mo, dy, yr ): def __repr__(self): def is. Leap. Year(self): def copy(self): """ returns a DIFFERENT object w/SAME date! ""“ return Date(self. month, self. day, self. year) def equals(self, d 2): """ returns True if they represent the same date; False otherwise """

class Date: More Date def __init__( self, mo, dy, yr ): def __repr__(self): def

class Date: More Date def __init__( self, mo, dy, yr ): def __repr__(self): def is. Leap. Year(self): def copy(self): """ returns a DIFFERENT object w/SAME date! ""“ return Date(self. month, self. day, self. year) def equals(self, d 2): """ returns True if they represent the same date; False otherwise ""“ return self. month == d 2. month and self. day == d 2. day and self. year == d 2. year

Good luck with the Exam!

Good luck with the Exam!