-2

this is famous path counting problem , i am trying to solve it using memoization. Enlighten me!

def pathCounter(a,b):
    matrix = [[0 for i in xrange(a)] for i in xrange(b)]

    if a==0 or b==0:
        return 1

    if matrix[a][b]:
        return matrix[a][b]

    print matrix[a][b]
    matrix[a][b]=pathCounter(a,b-1)+pathCounter(a-1,b)

    return matrix[2][2] 

if __name__=='__main__':
    k=pathCounter(2,2)
    print k
Mike Scotty
  • 10,530
  • 5
  • 38
  • 50

2 Answers2

0

I believe your trying to solve this problem.

If that is the case, then you are correct that it would be sensible to solve with recursion.

If you imagine each corner of the grid as a node, then you want to a recursive function that simply takes a parameter of the node it is at (x, y). In the function, it first needs to check if the position that it was called at is the bottom right vertex of the grid. If it is, the function adds one to the path count (as a path is finished when it reaches this corner) and then returns. Otherwise, this function just calls two more of itself (this is the recursion), one to its right (so y+1) and one to its left (x+1). An added step is to check that the coordinates are in the grid before calling them as a node in the middle of the bottom row for instance shouldn't call a node below it as that would be off the grid.

Now you have the recursive function defined, all you need to do now is declare a variable to store the path count. And call the recursive function from the coordinate (0,0).

However, as I am sure you have seen, this solution does not complete in reasonable time so it is necessary that you use memoization - speeding it up by caching the nodes so that the same sections of paths aren't calculated twice.

It also makes coding it more simple if as you have done, we work from the bottom right corner up to the top left corner. One last thing is that if you use a dictionary then the code becomes clearer.

The final code should look something like:

cache = {}

def pathCounter(x, y):
   if x == 0 or y == 0:
       return 1
   if (x,y) in cache:
      return cache[(x,y)]

   cache[(x,y)] = pathCounter(x, y-1) + pathCounter(x-1, y)
   return cache[(x,y)]

print(pathCounter(2,2))

this gives the expected result of 6.

I'll leave you to do the 20x20 grid. Hope this helps!

Joe Iddon
  • 20,101
  • 7
  • 33
  • 54
0

You made a few errors in your implementation of the algorithm. If your using a recursive approach you do not have to use the grid because you want require any of the stored data, actually. You only need to return the two possible sub-paths from your current position - that's it! Therefore, you need to make some changes in the main idea of your code.

I tried to keep as much of your original code as possible, but still make it working:

def pathCounterNaive(width, height, startX = 0, startY = 0):
    if startX >= width or startY >= height:
       return 0

   if startX == width-1 and startY == height-1:
      return 1

   return pathCounter(width,height, startX+1, startY) + pathCounter(width,height, startX, startY+1)

slowK=pathCounterNaive(3,3)
print(slowK)

Please keep in mind, that the parameters width and height represent the number of vertices, and are therefore not 2 but 3 for a 2x2 grid. As this code is using pure recursion it is very slow. If you want to use your memorization approach, you have to modify your code like this:

import numpy as np
def pathCounter(width, height):
    grid = np.zeros((height+1, width+1))
    def pathCounterInternal(x, y):
        if x==0 or y==0:
            return 1

        grid[x, y] = pathCounterInternal(x,y-1)+pathCounterInternal(x-1,y)

        return grid[x, y]

    grid[width, height] = pathCounterInternal(width, height)
    return grid[width, height]

k=pathCounter(2,2)
print(k)

Here you have to call it with 2 as the parameter for a 2x2 grid. This code is much faster due to the caching of already calculated paths.

zimmerrol
  • 4,872
  • 3
  • 22
  • 41
  • The OP asked to solve it using `memoization` and this is necessary for it to complete in reasnoble time for a larger grid size.... – Joe Iddon Sep 05 '17 at 09:08