Intro to Programming with Python Practical Session 5

  • Slides: 33
Download presentation
Intro to Programming with Python Practical Session #5 Recorsion, Dictionaries and Memoization

Intro to Programming with Python Practical Session #5 Recorsion, Dictionaries and Memoization

Plan Recursion Sloped Matrix Solving a maze Printing series of S Dictionaries Memorization Choose

Plan Recursion Sloped Matrix Solving a maze Printing series of S Dictionaries Memorization Choose k of n Fibonacci 2 source

Reminder - The Three Rules of Recursion 1. Base (termination) condition 2. Decomposition to

Reminder - The Three Rules of Recursion 1. Base (termination) condition 2. Decomposition to smaller instances 3. Use solutions of smaller instances to solve the original problem 3

Sloped Matrix A matrix will be sloped if: Dimension of Nx. N It consist

Sloped Matrix A matrix will be sloped if: Dimension of Nx. N It consist of numeric values only Zeros on its main diagonal Above main diagonal positive values Below main diagonal negative values 0 1 4 -2 0 5 -8 -1 0 -3 -9 -6 2 7 3 0 4

Sloped Matrix Write a function the gets a list of numeric values and answer

Sloped Matrix Write a function the gets a list of numeric values and answer True/False whether it is sloped or not. lst = [[0, 1, 4, 2], [-2, 0, 5, 7], [-8, -1, 0, 3], [-3, -9, -6, 0]] >>>is_sloped(lst) True lst = [[0, -1, 4, 2], [-2, 0, 5, 7], [-8, -1, 0, 3], [-3, -9, -6, 0]] >>>is_sloped(lst) False

Sloped Matrix What is the base condition? An empty list? A list of a

Sloped Matrix What is the base condition? An empty list? A list of a single list with a single value? How can we decompose this problem into a smaller one? A smaller matrix? How? What will we do with our smaller problem solution? What operators should we use?

Sloped Matrix 0 1 -2 0 -8 -1 4 5 0 0 -2 -8

Sloped Matrix 0 1 -2 0 -8 -1 4 5 0 0 -2 -8 0 1 4 0 5 -1 0

Sloped Matrix

Sloped Matrix

Solving a Maze Our maze will be a list of integers. 1 will symbol

Solving a Maze Our maze will be a list of integers. 1 will symbol a cell we can walk into 0 will symbol a wall We need to get from cell [i][j] to the last cell in the maze (cell[n-1][m-1]) We can move left, right, down, up. We would like to answer True/False if the maze can be solved and also mark the path for solving the maze with a unique value – ‘#’ , and any cell we visited and is not part of the path will be marked with ‘X’

 X XX 1110110001111 XXX X 101111001 X X X 000010100 X XX X

X XX 1110110001111 XXX X 101111001 X X X 000010100 X XX X 111010111 XXX X 1010000111001 X XXXXXX X 1011111101111 X 1000000 X XXXXXX 1111111

 # ## 1110110001111 ### # 101111001 # # # 000010100 # ## #

# ## 1110110001111 ### # 101111001 # # # 000010100 # ## # 111010111 ### # 1010000111001 # ###### # 1011111101111 # 1000000 ### # # ###### 1111111

 # ## 1110110001111 ### X 101111001 # # # 000010100 # ## #

# ## 1110110001111 ### X 101111001 # # # 000010100 # ## # 111010111 ##X # 1010000111001 # ###### # 1011111101111 # 1000000 # ###### 1111111

Solving a maze

Solving a maze

Series of sum S Given list of numeric values lst and another numeric value

Series of sum S Given list of numeric values lst and another numeric value S Print all the sub-groups of lst that sums to S What is our base condition? S==0 What else do we need? A ‘container’ list for holding on to all element of lst that might sums to S And a bit more…

Series of sum S

Series of sum S

And now…. Dictionaries

And now…. Dictionaries

Dictionary K # Empty dictionary e l y >>> tel = {} u e

Dictionary K # Empty dictionary e l y >>> tel = {} u e # Define a new dictionary >>> tel = {'jack': 4098, 'sape': 4139} # Add (or replace) a pair >>> tel['guido'] = 4127 >>> tel {'sape': 4139, 'guido': 4127, 'jack': 4098} # What is the value of the key 'jack'? >>> tel['jack'] 4098 17 a V • A dictionary maps keys to values. • Keys aren’t necessarily of the same type, and so are values.

Dictionary example >>> tel {'sape': 4139, 'jack': 4098, 'guido': 4127} >>> tel['abby'] Traceback (most

Dictionary example >>> tel {'sape': 4139, 'jack': 4098, 'guido': 4127} >>> tel['abby'] Traceback (most recent call last): File "<pyshell#23>", line 1, in <module> tel['abby'] Key. Error: 'abby'

What can be used as a key? Immutable Strings Numbers Tuples But types only!

What can be used as a key? Immutable Strings Numbers Tuples But types only! remember… If a tuple contains any mutable objects either directly or indirectly, it cannot be used as a key >>> a={} >>> a[(1, 2, 3, [1, 2])] = "wrong" Traceback (most recent call last): File "<pyshell#35>", line 1, in <module> a[(1, 2, 3, [1, 2])]="wrong" Type. Error: unhashable type: 'list'

Some dictionary methods D. get(k, [d]) -- return D[k] if D has key k,

Some dictionary methods D. get(k, [d]) -- return D[k] if D has key k, otherwise d (default: d=None). k in D -- True if D has a key k, False otherwise. D. pop(k, [d]) -- remove the specified pair with key k and return its value. If k is not in D, return d. D. keys() -- list of D's keys, arbitrary order. D. values() -- list of D's values, arbitrary order. D. items() -- list of tuples (key, value), arbitrary order.

Dictionary methods example # delete a pair >>> tel. pop('sape‘) {'sape': 4139, 'jack': 4098,

Dictionary methods example # delete a pair >>> tel. pop('sape‘) {'sape': 4139, 'jack': 4098, 'guido': 4127, irv': 3555} # get the keys - returns a list, order is arbitrary >>> tel. keys() ['guido', 'irv', 'jack'] # check if a key is in tel >>> 'guido' in tel True # Get value of key. >>> tel. get('jack') 4098 >>> tel. get('Jack', 'Missing') 'Missing'

Other methods: dict(), update() # Input: a list of pairs (tuples or lists) >>>

Other methods: dict(), update() # Input: a list of pairs (tuples or lists) >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127} # Update: add dict 2 to dict 1 >>> dict 1 = {'Name': 'Zara', 'Age': 7} >>> dict 2 = {‘Gender': 'female' } >>> dict 1. update(dict 2) >>> dict 1 {'Age': 7, 'Name': 'Zara', ‘Gender': 'female'}

Example 1 You are given a nested list of student names and grades. >>>

Example 1 You are given a nested list of student names and grades. >>> students = [["arya", 87], ["jon", 88], ["bran", 100]] Given a name we want to know the grade. >>> get_grade(students, "arya") 87 # using a list def get_grade(students, name): for stud in students: if stud[0]==name: return stud[1] # using a dictionary >>> students_dict = dict(students) >>> students_dict {'arya': 87, 'bran': 100, 'jon': 88} >>> students_dict. get('arya') Using a dict for mapping is more straightforward than using a list – and typically also works faster.

Example 2: sparse matrix >>> matrix = [ [0, 0, 0, 1, [0, 0,

Example 2: sparse matrix >>> matrix = [ [0, 0, 0, 1, [0, 0, [0, 2, 0, 0, [0, 0, 0, 3, >>> matrix[1][2] 0 >> >matrix[0][3] 1 0], 0], 0]] • In this matrix there are only 3 non-zero entries. • Saving all zeros in a list is a waste of space. • As a dict: A key is a tuple, indicating the rowcolumn intersection where the non-zero value is. >>> matrix = {(0, 3): 1, (2, 1): 2, (4, 3): 3} >>> matrix. get((1, 2), 0) 0 >>> matrix. get((0, 3), 0) 1

Example 3: pangrams A pangram is a sentence that contains each letter of the

Example 3: pangrams A pangram is a sentence that contains each letter of the English alphabet at least once. def is_pangram(s): d = {} for char in s: if char. isalpha(): d[char. lower()]=True return len(d. keys())==26 • Because the English alphabet has only 26 letters, we could also solve this with a list, initialized as: [False] * 26 • However, if the alphabet had 10, 000 letters … dict would certainly be better. >>> s = " The quick brown fox jumps over the lazy dog" >>> print is_pangram(s) True >>> s = " The quick brown jumps over the lazy dog" >>> print is_pangram(s) False

Memoization An optimization technique used primarily to speed up computer programs Storing the results

Memoization An optimization technique used primarily to speed up computer programs Storing the results of expensive function calls Returning the cached result when the same inputs occur again.

Choose k elements from n - Combination Recursive formula: Termination Criteria: k == 0

Choose k elements from n - Combination Recursive formula: Termination Criteria: k == 0 1 k == n 1 (n < k 0) 27

Choose k from n –Code def choose(n, k): if k==0 or n==k: return 1

Choose k from n –Code def choose(n, k): if k==0 or n==k: return 1 if n < k: # optional, not necessary return 0 return choose(n - 1, k - 1) + choose(n -1, k) 28 Python Tutor

Choose k from n – Recursion Tree n=4 k=2 >>> choose(4, 2) n=3 k=2

Choose k from n – Recursion Tree n=4 k=2 >>> choose(4, 2) n=3 k=2 n=3 k=1 n=1 k=0 Note the redundant calls n=1 k=1 n=2 k=2 n=2 k=1 n=2 k=0 n=2 k=1 n=1 k=0 n=1 k=1 29 Python Tutor

Solution – Use Memoization! def choose_memo(n, k, memo=None): if k==0 or n==k: return 1

Solution – Use Memoization! def choose_memo(n, k, memo=None): if k==0 or n==k: return 1 if n < k: #optional return 0 if memo == None: memo = {} mem_key = (n, k) if mem_key not in memo: memo[mem_key] = choose_memo(n - 1, k – 1, memo) + choose_memo(n - 1, k, memo) return memo[mem_key]

Fibonacci memoization fib(5) fib(4) fib(3) fib(1) fib(2) fib(0) fib(1) fib(0)

Fibonacci memoization fib(5) fib(4) fib(3) fib(1) fib(2) fib(0) fib(1) fib(0)

Fibonacci memoization § We may definitely use memoization here to solve this problem much

Fibonacci memoization § We may definitely use memoization here to solve this problem much faster (for large N) § Each time we will have to calculate Fibonacci(N) we will ok for it in a dictionary with N as key. § If the N is not part ok the dictionary keys, we will calculate Fibonacci(n) and add the result to the dictionary 32

Fibonacci with/out memorization comparison

Fibonacci with/out memorization comparison