Is there a simple way to memoize results? my dynamic programming solution is potentially calling the same function, with the same parameters, multiple times.
I think memoizing would add speed. However, I'm not sure what the best approach is. Here's the original function, which works, albeit, it's not memoized:
def dim(M):
rows = len(M)
cols = len(M[0])
return rows, cols
def minimumCostPath(matrix, i=0, j=0, total=0):
r,c = dim(matrix)
if i+1 < r and j+1 < c:
down = matrix[i+1][j]
right = matrix[i][j+1]
return min(minimumCostPath(matrix, i+1, j, total+down),
minimumCostPath(matrix, i, j+1, total+right))
elif i+1 < r:
right = matrix[i+1][j]
return minimumCostPath(matrix, i+1, j, total+right)
elif j+1 < c:
down = matrix[i][j+1]
return minimumCostPath(matrix, i, j+1, total+down)
else:
return total + matrix[0][0]
test = [ [23,70,54],
[86,5,13],
[86,62,77],
[60,37,32],
[88,58,98] ]
total = minimumCostPath(test)
>>>
318
Below is my attempt to memoize this function with a matrix (nested list) of zeros.
def solution(matrix):
cache = [[0 for j in range(len(matrix[0]))] for i in range(len(matrix))]
return helper(matrix, cache, i=0, j=0, total=0)
def helper(matrix, cache, i=0, j=0, total=0):
r,c = dim(matrix)
if i+1 < r and j+1 < c:
down = matrix[i+1][j]
right = matrix[i][j+1]
if cache[i+1][j] > 0:
go_down = cache[i+1][j] + down
else:
go_down = helper(matrix, cache, i+1, j, total+down)
cache[i+1][j] = go_down
if cache[i][j+1] > 0 :
go_right = cache[i][j+1] + right
else:
go_right = helper(matrix, cache, i, j+1, total+right)
cache[i][j+1] = go_right
return min(go_down, go_right)
elif i+1 < r:
down = matrix[i+1][j]
if cache[i+1][j] > 0:
go_down = cache[i+1][j] + down
else:
go_down = helper(matrix, cache, i+1, j, total+down)
cache[i+1][j] = go_down
return go_down
elif j+1 < c:
right = matrix[i][j+1]
if cache[i][j+1] > 0 :
go_right = cache[i][j+1] + right
else:
go_right = helper(matrix, cache, i, j+1, total+right)
cache[i][j+1] = go_right
return go_right
else:
return total + matrix[0][0]
solution(test)
Two problems.
- I'm getting an error,
TypeError: '<' not supported between instances of 'NoneType' and 'int'line 23 is evaluating either go_right or go_down as None, which is peculiar. - It's not very succinct or pretty. Perhaps a better helper function would simplify the code.
Lastly, I do understand that there is the bottom-up approach, which does not use recursion but rather fills in table cells, iteratively. At this point, I'm wondering how the recursive solution could leverage memoization, not start from scratch on bottom up implementation.