15-112 Fundamentals of Programming Week 5 - Lecture 3: More - - PowerPoint PPT Presentation

15 112 fundamentals of programming
SMART_READER_LITE
LIVE PREVIEW

15-112 Fundamentals of Programming Week 5 - Lecture 3: More - - PowerPoint PPT Presentation

15-112 Fundamentals of Programming Week 5 - Lecture 3: More Advanced Recursion June 15, 2016 Recursion vs Iteration 15-112 View Recursion Iteration - Elegance + - Performance + Debugability - + Memoization def fib(n): if (n <


slide-1
SLIDE 1

15-112 Fundamentals of Programming

Week 5 - Lecture 3: More Advanced Recursion

June 15, 2016

slide-2
SLIDE 2

Recursion vs Iteration

Elegance Performance Debugability Recursion Iteration + + +

  • 15-112 View
slide-3
SLIDE 3

Memoization

def fib(n): if (n < 2): result = 1 else: result = fib(n-1) + fib(n-2) return result print(fib(6))

How many times is fib(2) computed? 5

slide-4
SLIDE 4

Memoization

fibResults = dict() def fib(n): if (n in fibResults): return fibResults[n] if (n < 2): result = 1 else: result = fib(n-1) + fib(n-2) fibResults[n] = result return result

slide-5
SLIDE 5

Expanding the stack size and recursion limit

def rangeSum(lo, hi): if (lo > hi): return 0 else: return lo + rangeSum(lo+1, hi) print(rangeSum(1, 1234)) # RuntimeError: maximum recursion depth exceeded print(callWithLargeStack(rangeSum(1, 123456))) # Works

slide-6
SLIDE 6

More Examples

slide-7
SLIDE 7

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

slide-8
SLIDE 8

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

slide-9
SLIDE 9

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

All subsets = All subsets that do not contain 1 +

slide-10
SLIDE 10

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

All subsets = All subsets that do not contain 1 +

slide-11
SLIDE 11

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

All subsets = All subsets that do not contain 1 + All subsets that contain 1

slide-12
SLIDE 12

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

All subsets = All subsets that do not contain 1 + All subsets that contain 1 [1] + subset that doesn’t contain a 1

slide-13
SLIDE 13

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

def powerset(a): else: allSubsets = [ ] for subset in powerset(a[1:]): allSubsets += [subset] allSubsets += [[a[0]] + subset] return allSubsets if (len(a) == 0): return [[]]

slide-14
SLIDE 14

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

def powerset(a): else: allSubsets = [ ] for subset in powerset(a[1:]): allSubsets += [subset] allSubsets += [[a[0]] + subset] return allSubsets if (len(a) == 0): return [[]]

slide-15
SLIDE 15

Power set

Given a list, return a list of all the subsets of the list.

[1,2,3] -> [[], [1], [2], [3], [1,2], [2,3], [1,3], [1,2,3]]

def powerset(a): else: allSubsets = [ ] for subset in powerset(a[1:]): allSubsets += [subset] allSubsets += [[a[0]] + subset] return allSubsets if (len(a) == 0): return [[]]

slide-16
SLIDE 16

Permutations

Given a list, return all permutations of the list.

[1,2,3] -> [[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]]

slide-17
SLIDE 17

Permutations

Given a list, return all permutations of the list.

[1,2,3] -> [[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]] [1,2,3], [2,1,3], [2,3,1]

slide-18
SLIDE 18

Permutations

Given a list, return all permutations of the list.

[1,2,3] -> [[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]] [1,3,2], [3,1,2], [3,2,1] [1,2,3], [2,1,3], [2,3,1]

slide-19
SLIDE 19

Permutations

[1,2,3,4] [2,3,4] [2,4,3] [3,2,4] [3,4,2] [4,2,3] [4,3,2]

Permutations of [2,3,4]

[1,2,3,4] [2,1,3,4] [2,3,1,4] [2,3,4,1] [1,2,4,3] [2,1,4,3] [2,4,1,3] [2,4,3,1]

. . . . . .

slide-20
SLIDE 20

Permutations

Given a list, return all permutations of the list.

[1,2,3] -> [[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]]

def permutations(a): else: allPerms = [ ] for subPermutation in permutations(a[1:]): for i in range(len(subPermutation)+1): allPerms += [subPermutation[:i] + [a[0]] + subPermutation[i:]] return allPerms if (len(a) == 0): return [[]]

slide-21
SLIDE 21

Permutations

Given a list, return all permutations of the list.

[1,2,3] -> [[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]]

def permutations(a): if (len(a) == 0): return [[]] else: allPerms = [ ] for subPermutation in permutations(a[1:]): for i in range(len(subPermutation)+1): allPerms += [subPermutation[:i] + [a[0]] + subPermutation[i:]] return allPerms

slide-22
SLIDE 22

Permutations

Given a list, return all permutations of the list.

def permutations(a): if (len(a) == 0): return [[]] else: allPerms = [ ] for subPermutation in permutations(a[1:]): for i in range(len(subPermutation)+1): allPerms += [subPermutation[:i] + [a[0]] + subPermutation[i:]] return allPerms

[1,2,3] -> [[1,2,3], [2,1,3], [2,3,1], [1,3,2], [3,1,2], [3,2,1]]

slide-23
SLIDE 23

Print files in a directory

slide-24
SLIDE 24

Print files in a directory

slide-25
SLIDE 25

Print files in a directory

import os def printFiles(path): if (os.path.isdir(path) == False): # base case: not a folder, but a file, so print its path print(path) else: # recursive case: it's a folder for filename in os.listdir(path): printFiles(path + "/" + filename)

slide-26
SLIDE 26

nQueens Problem

slide-27
SLIDE 27

nQueens Problem

Place n queens on a n by n board so that no queen is attacking another queen.

—> [6, 4, 2, 0, 5, 7, 1, 3]

list of rows

def solve(n):

slide-28
SLIDE 28

nQueens Problem

Place n queens on a n by n board so that no queen is attacking another queen. n rows and n-1 columns

  • ne queen has to be on first column
slide-29
SLIDE 29

nQueens Problem

First attempt:

  • try rows 0 to 7 for first queen
  • for each try, recursively solve

the red part Problem: Can’t solve red part without taking into account first queen First queen puts constraints on the solution to the red part Need to be able to solve nQueens with added constraints.

def solve(n, m, constraints):

Need to generalize our function:

slide-30
SLIDE 30

nQueens Problem

def solve(n, m, constraints):

n = number or rows m = number or columns constraints (in what form?) list of rows For the red part, we have the constraint [6]

slide-31
SLIDE 31

nQueens Problem

def solve(n, m, constraints):

n = number or rows m = number or columns constraints (in what form?) list of rows For the red part, we have the constraint [6,4,2] The constraint tells us which cells are unusable for the red part.

To solve original nQueens problem, call: solve(n, n, [])

slide-32
SLIDE 32

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[?,?,?,?,?]

def solve(n, m, constraints):

slide-33
SLIDE 33

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

def solve(n, m, constraints):

slide-34
SLIDE 34

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

def solve(n, m, constraints):

[5,7,1,3]

slide-35
SLIDE 35

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

[5,7,1,3] —> [0,5,7,1,3]

def solve(n, m, constraints):

slide-36
SLIDE 36

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

Suppose no solution

def solve(n, m, constraints):

slide-37
SLIDE 37

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

def solve(n, m, constraints):

slide-38
SLIDE 38

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

NOT LEGAL

def solve(n, m, constraints):

slide-39
SLIDE 39

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

NOT LEGAL

def solve(n, m, constraints):

slide-40
SLIDE 40

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

NOT LEGAL

def solve(n, m, constraints):

slide-41
SLIDE 41

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

NOT LEGAL

def solve(n, m, constraints):

slide-42
SLIDE 42

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

def solve(n, m, constraints):

slide-43
SLIDE 43

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

no solution

def solve(n, m, constraints):

slide-44
SLIDE 44

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

NOT LEGAL

def solve(n, m, constraints):

slide-45
SLIDE 45

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

def solve(n, m, constraints):

slide-46
SLIDE 46

nQueens Problem

n = 8 m = 5 constraints = [6,4,2]

[0,?,?,?,?]

no solution

def solve(n, m, constraints):

slide-47
SLIDE 47

nQueens Problem

def solve(n, m, constraints): if(m == 0): return []

n = 8 m = 5 constraints = [6,4,2]

return False for row in range(n): if (isLegal(row, constraints)):

[0,?,?,?,?]

newConstraints = constraints + [row] result = solve(n, m-1, newConstraints) if (result != False): return [row] + result

slide-48
SLIDE 48

nQueens Problem

def isLegal(row, constraints): for ccol in range(len(constraints)): crow = constraints[ccol] shift = len(constraints) - ccol if ((row == crow) or (row == crow + shift) or (row == crow - shift)): return False return True

n = 8 m = 5 constraints = [6,4,2]

slide-49
SLIDE 49

nQueens Problem

def isLegal(row, constraints): for ccol in range(len(constraints)): crow = constraints[ccol] shift = len(constraints) - ccol if ((row == crow) or (row == crow + shift) or (row == crow - shift)): return False return True

n = 8 m = 5 constraints = [6,4,2]

slide-50
SLIDE 50

nQueens Problem

def isLegal(row, constraints): for ccol in range(len(constraints)): crow = constraints[ccol] shift = len(constraints) - ccol if ((row == crow) or (row == crow + shift) or (row == crow - shift)): return False return True

n = 8 m = 5 constraints = [6,4,2]

slide-51
SLIDE 51

nQueens Problem

def isLegal(row, constraints): for ccol in range(len(constraints)): crow = constraints[ccol] shift = len(constraints) - ccol if ((row == crow) or (row == crow + shift) or (row == crow - shift)): return False return True

n = 8 m = 5 constraints = [6,4,2]

slide-52
SLIDE 52

Solving a maze puzzle

start finish

slide-53
SLIDE 53

Solving a maze puzzle

start finish

slide-54
SLIDE 54

Solving a maze puzzle

start finish

def isSolvable(maze, (rowStart, colStart), (rowEnd, colEnd)): —> True or False Main Idea: if isSolvable(maze, (rowStart, colStart), (rowEnd, colEnd)), then for some neighbor (rowN, colN) of (rowStart, colStart), isSolvable(maze, (rowN, colN), (rowEnd, colEnd))

slide-55
SLIDE 55

Solving a maze puzzle

def isSolvable(maze, (rowStart, colStart), (rowEnd, colEnd)): if ((rowStart, colStart) == (rowEnd, colEnd)): return True

U D R L

return False for dir in [(-1,0), (1,0), (0,1), (0,-1)]: newCell = (rowStart, colStart) + dir if (isLegal(maze, newCell) and isSolvable(maze, newCell, (rowEnd, colEnd))): return True

Where is the bug?

slide-56
SLIDE 56

Solving a maze puzzle

def isSolvable(maze, (rowStart, colStart), (rowEnd, colEnd)): if ((rowStart, colStart) == (rowEnd, colEnd)): return True for dir in [(-1,0), (1,0), (0,1), (0,-1)]: newCell = (rowStart, colStart) + dir if (isLegal(maze, newCell) and isSolvable(maze, newCell, (rowEnd, colEnd))): return True if ((rowStart, colStart) in visited): return False visited.add((rowStart, colStart))

visited = set()

return False

slide-57
SLIDE 57

Solving a maze puzzle

def isSolvable(maze, (rowStart, colStart), (rowEnd, colEnd)): if ((rowStart, colStart) == (rowEnd, colEnd)): return True return False for dir in [(-1,0), (1,0), (0,1), (0,-1)]: newCell = (rowStart, colStart) + dir if (isLegal(maze, newCell) and isSolvable(maze, newCell, (rowEnd, colEnd))): return True if ((rowStart, colStart) in visited): return False visited.add((rowStart, colStart))

visited = set()

solution.remove((rowStart, colStart))

solution = set()

solution.add((rowStart, colStart))

slide-58
SLIDE 58

Flood fill

click

def floodFill(x, y, color): if ((not inImage(x,y)) or (getColor(img, x, y) == color)): return img.put(color, to=(x, y)) floodFill(x-1, y, color) floodFill(x+1, y, color) floodFill(x, y-1, color) floodFill(x, y+1, color)

U D R L

slide-59
SLIDE 59

Fractals

A change rule: length

length/3

slide-60
SLIDE 60

Fractals: kochSnowflake

n = 1 n = 2 n = 3 n = 4

def kochSide(length, n): if (n == 1): turtle.forward(length) else: kochSide(length/3, n-1) turtle.left(60) kochSide(length/3, n-1) turtle.right(120) kochSide(length/3, n-1) turtle.left(60) kochSide(length/3, n-1)

slide-61
SLIDE 61

Fractals: kochSnowflake

def kochSnowflake(length, n): # just call kochSide 3 times for step in range(3): kochSide(length, n) turtle.right(120)

slide-62
SLIDE 62

Fractals: Sierpinski Triangle

level 0 level 1 level 2

def drawST(x, y, size, level): # (x, y) is the bottom-left corner of the triangle if (level == 0): canvas.create_polygon((x, y), (x+size, y), (x+size/2, y-size*(3**0.5)/2), fill=“black” ) else: drawST(x, y, size/2, level-1) drawST(x+size/2, y, size/2, level-1) drawST(x+size/4, y-size*(3**0.5)/4, size/2, level-1)