def findIndex(c, m2d):
return [(x,y) for x,v in enumerate(m2d) for y,n in enumerate(v)
if n == c][0]
def neighbourhood(x,y,m2d):
return ((x+i,y+j) for i,j in [(0,1),(0,-1),(1,0),(-1,0)]
if m2d[x+i][y+j] != '#')
def diff(x,y): return abs(x[0]-y[0]) + abs(x[1]-y[1])
def solve(m2d):
start, goal = findIndex('S', m2d), findIndex('G', m2d)
openN, closeN = {start:(diff(start,goal), start)}, {}
while openN != {}:
(n,r) = sorted(openN.iteritems(), key=lambda(k,v):v[0])[0]
closeN[n] = openN.pop(n)
if n == goal: break
for (x,y) in neighbourhood(n[0], n[1], m2d):
v = r[0] - diff(goal,n) + diff(goal,(x,y)) + 1
if (x,y) in openN and v < openN[x,y][0]:
openN[x,y] = (v, n)
if (x,y) in closeN and v < closeN[x,y][0]:
openN[x,y] = (v, n)
closeN.pop(x,y)
if (x,y) not in openN and (x,y) not in closeN:
openN[x,y] = (v,n)
print_path(start, goal, closeN)
def print_path(start, goal, closeN):
path, x = [], goal
while x != start:
y = closeN[x][1]
if x[0] > y[0]: path.append('d')
elif x[0] < y[0]: path.append('u')
elif x[1] > y[1]: path.append('r')
elif x[1] < y[1]: path.append('l')
x = y
print(''.join(reversed(path)))
solve([
'#######',
'#.....#',
'#.G.#.#',
'#..#..#',
'#.#.S.#',
'#.....#',
'#######'])
ZGVmIGZpbmRJbmRleChjLCBtMmQpOgogICAgcmV0dXJuIFsoeCx5KSBmb3IgeCx2IGluIGVudW1lcmF0ZShtMmQpIGZvciB5LG4gaW4gZW51bWVyYXRlKHYpCiAgICAgICAgICAgIGlmIG4gPT0gY11bMF0KCmRlZiBuZWlnaGJvdXJob29kKHgseSxtMmQpOgogICAgcmV0dXJuICgoeCtpLHkraikgZm9yIGksaiBpbiBbKDAsMSksKDAsLTEpLCgxLDApLCgtMSwwKV0KICAgICAgICAgICAgaWYgbTJkW3graV1beStqXSAhPSAnIycpCgpkZWYgZGlmZih4LHkpOiByZXR1cm4gYWJzKHhbMF0teVswXSkgKyBhYnMoeFsxXS15WzFdKQoKZGVmIHNvbHZlKG0yZCk6CiAgICBzdGFydCwgZ29hbCA9IGZpbmRJbmRleCgnUycsIG0yZCksIGZpbmRJbmRleCgnRycsIG0yZCkKICAgIG9wZW5OLCBjbG9zZU4gPSB7c3RhcnQ6KGRpZmYoc3RhcnQsZ29hbCksIHN0YXJ0KX0sIHt9CiAgICB3aGlsZSBvcGVuTiAhPSB7fToKICAgICAgICAobixyKSA9IHNvcnRlZChvcGVuTi5pdGVyaXRlbXMoKSwga2V5PWxhbWJkYShrLHYpOnZbMF0pWzBdCiAgICAgICAgY2xvc2VOW25dID0gb3Blbk4ucG9wKG4pCiAgICAgICAgaWYgbiA9PSBnb2FsOiBicmVhawogICAgICAgIGZvciAoeCx5KSBpbiBuZWlnaGJvdXJob29kKG5bMF0sIG5bMV0sIG0yZCk6CiAgICAgICAgICAgIHYgPSByWzBdIC0gZGlmZihnb2FsLG4pICsgZGlmZihnb2FsLCh4LHkpKSArIDEKICAgICAgICAgICAgaWYgKHgseSkgaW4gb3Blbk4gYW5kIHYgPCBvcGVuTlt4LHldWzBdOgogICAgICAgICAgICAgICAgb3Blbk5beCx5XSA9ICh2LCBuKQogICAgICAgICAgICBpZiAoeCx5KSBpbiBjbG9zZU4gYW5kIHYgPCBjbG9zZU5beCx5XVswXToKICAgICAgICAgICAgICAgIG9wZW5OW3gseV0gPSAodiwgbikKICAgICAgICAgICAgICAgIGNsb3NlTi5wb3AoeCx5KQogICAgICAgICAgICBpZiAoeCx5KSBub3QgaW4gb3Blbk4gYW5kICh4LHkpIG5vdCBpbiBjbG9zZU46CiAgICAgICAgICAgICAgICBvcGVuTlt4LHldID0gKHYsbikKICAgIHByaW50X3BhdGgoc3RhcnQsIGdvYWwsIGNsb3NlTikKCmRlZiBwcmludF9wYXRoKHN0YXJ0LCBnb2FsLCBjbG9zZU4pOgogICAgcGF0aCwgeCA9IFtdLCBnb2FsCiAgICB3aGlsZSB4ICE9IHN0YXJ0OgogICAgICAgIHkgPSBjbG9zZU5beF1bMV0KICAgICAgICBpZiB4WzBdID4geVswXTogcGF0aC5hcHBlbmQoJ2QnKQogICAgICAgIGVsaWYgeFswXSA8IHlbMF06IHBhdGguYXBwZW5kKCd1JykKICAgICAgICBlbGlmIHhbMV0gPiB5WzFdOiBwYXRoLmFwcGVuZCgncicpCiAgICAgICAgZWxpZiB4WzFdIDwgeVsxXTogcGF0aC5hcHBlbmQoJ2wnKQogICAgICAgIHggPSB5CiAgICBwcmludCgnJy5qb2luKHJldmVyc2VkKHBhdGgpKSkKCgpzb2x2ZShbCicjIyMjIyMjJywKJyMuLi4uLiMnLAonIy5HLiMuIycsCicjLi4jLi4jJywKJyMuIy5TLiMnLAonIy4uLi4uIycsCicjIyMjIyMjJ10p