Advertisement
kartikkukreja

N-puzzle problem with A*

Dec 28th, 2013
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.93 KB | None | 0 0
  1. from Queue import heapq as hq
  2. from copy import deepcopy
  3.  
  4. k, N, goal = [None] * 3
  5.  
  6. class State:
  7.     def __init__(self, sig):
  8.         self.sig = deepcopy(sig)
  9.         for i in xrange(N):
  10.             if self.sig[i] == 0:
  11.                 self.pos0 = i
  12.                 break
  13.         self.h = self.__heuristic__()
  14.         self.str = self.__toStr__()
  15.  
  16.     def __toStr__(self):
  17.         return reduce(lambda x, y: x + str(y), self.sig, '')
  18.    
  19.     def __str__(self):
  20.         return self.str
  21.  
  22.     # Goal configuration [0, 1, ..., k*k-1] has been hardcoded
  23.     # to get an efficient implementation
  24.     def __moveCount__(self, i):
  25.         if self.sig[i] == 0:
  26.             return 0
  27.         return abs((i / k) - (self.sig[i] / k)) + abs((i % k) - (self.sig[i] % k))
  28.  
  29.     def __heuristic__(self):
  30.         return reduce(lambda x, y: x + self.__moveCount__(y), xrange(N), 0)
  31.  
  32.     # Manhattan distance
  33.     def heuristic(self):
  34.         return self.h
  35.  
  36.     def moves(self):
  37.         candidates = []
  38.         copy = deepcopy(self.sig)
  39.         if self.pos0 >= k:
  40.             copy[self.pos0], copy[self.pos0 - k] = copy[self.pos0 - k], copy[self.pos0]
  41.             candidates.append([State(copy), 'U'])
  42.             copy[self.pos0], copy[self.pos0 - k] = copy[self.pos0 - k], copy[self.pos0]
  43.         if self.pos0 < N-k:
  44.             copy[self.pos0], copy[self.pos0 + k] = copy[self.pos0 + k], copy[self.pos0]
  45.             candidates.append([State(copy), 'D'])
  46.             copy[self.pos0], copy[self.pos0 + k] = copy[self.pos0 + k], copy[self.pos0]
  47.         if (self.pos0 % k) > 0:
  48.             copy[self.pos0], copy[self.pos0 - 1] = copy[self.pos0 - 1], copy[self.pos0]
  49.             candidates.append([State(copy), 'L'])
  50.             copy[self.pos0], copy[self.pos0 - 1] = copy[self.pos0 - 1], copy[self.pos0]
  51.         if (self.pos0 % k) < k-1:
  52.             copy[self.pos0], copy[self.pos0 + 1] = copy[self.pos0 + 1], copy[self.pos0]
  53.             candidates.append([State(copy), 'R'])
  54.             copy[self.pos0], copy[self.pos0 + 1] = copy[self.pos0 + 1], copy[self.pos0]
  55.         return candidates
  56.  
  57.     def isGoal(self):
  58.         return self.sig == goal
  59.  
  60. def astar(start):
  61.     pq = []
  62.     closed = set()
  63.     hq.heappush(pq, [start.heuristic(), 0, start, []])
  64.     while pq:
  65.         f, g, cur, path = hq.heappop(pq)
  66.         if cur.isGoal():
  67.             return g, path
  68.         closed.add(str(cur))
  69.         for child, move in cur.moves():
  70.             if str(child) not in closed:
  71.                 p = deepcopy(path)
  72.                 p.append(move)
  73.                 hq.heappush(pq, [g+1 + child.heuristic(), g+1, child, p])
  74.     return None
  75.  
  76. if __name__ == "__main__":
  77.     k = int(raw_input())
  78.     N = k * k
  79.     pattern = [int(raw_input()) for i in xrange(N)]
  80.     goal = [i for i in xrange(N)]
  81.     count, path = astar(State(pattern))
  82.     moves = {'U':'UP', 'D':'DOWN', 'L':'LEFT', 'R':'RIGHT'}
  83.     print count
  84.     for move in path:
  85.         print moves[move]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement