-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path8puzzle.py
More file actions
157 lines (132 loc) · 4.08 KB
/
Copy path8puzzle.py
File metadata and controls
157 lines (132 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from heapq import heappush, heappop
from random import shuffle
import time
class Solver:
def __init__(self, initial_state=None):
self.initial_state = State(initial_state)
self.goal = range(0, 9)
#self.goal.append(0);
def _rebuildPath(self, end):
path = [end]
state = end.parent
while state.parent:
path.append(state)
state = state.parent
return path
def solve(self):
frontier = PriorityQueue()
frontier.add(self.initial_state)
explored = set()
moves = 0
print 'Initial State'
print frontier.peek(), '\n\n'
while frontier:
#print frontier[0].score()
current = frontier.poll()
if current.values == self.goal:
print 'Result'
path = self._rebuildPath(current)
for state in reversed(path):
print state
print 'solved %d Movements' % len(path)
break
moves += 1
for state in current.possible_moves(moves):
if state not in explored:
frontier.add(state)
explored.add(current)
class State:
def __init__(self, values, moves=0, parent=None):
self.values = values
self.moves = moves
self.parent = parent
self.goal = range(0, 9)
#self.goal.append(0);
def possible_moves(self, moves):
# obtainig the possible actions
i = self.values.index(0)
if i in [3, 4, 5, 6, 7, 8]:
new_board = self.values[:]
new_board[i], new_board[i - 3] = new_board[i - 3], new_board[i]
yield State(new_board, moves, self)
if i in [1, 2, 4, 5, 7, 8]:
new_board = self.values[:]
new_board[i], new_board[i - 1] = new_board[i - 1], new_board[i]
yield State(new_board, moves, self)
if i in [0, 1, 3, 4, 6, 7]:
new_board = self.values[:]
new_board[i], new_board[i + 1] = new_board[i + 1], new_board[i]
yield State(new_board, moves, self)
if i in [0, 1, 2, 3, 4, 5]:
new_board = self.values[:]
new_board[i], new_board[i + 3] = new_board[i + 3], new_board[i]
yield State(new_board, moves, self)
def score(self):
return self._h() + self._g()
def _h(self):
#index to coordinates
coordinates = {0:[0,0],1:[0,1],2:[0,2],3:[1,0],4:[1,1],5:[1,2],6:[2,0],7:[2,1],8:[2,2]}
manhattan_distance = 1;
for i in self.values:
pos_state=coordinates[self.values.index(i)]
pos_goal=coordinates[self.goal.index(i)]
manhattan_distance += (abs(pos_goal[0]-pos_state[0]) + abs(pos_goal[1]-pos_state[1]))
return manhattan_distance;
def _g(self):
return self.moves
def __cmp__(self, other):
return self.values == other.values
def __eq__(self, other):
return self.__cmp__(other)
def __hash__(self):
return hash(str(self.values))
def __lt__(self, other):
return self.score() < other.score()
def __str__(self):
print
return '\n'.join([str(self.values[:3]),
str(self.values[3:6]),
str(self.values[6:9])]).replace('[', '').replace(']', '').replace(',', '').replace('0', ' ')
class PriorityQueue:
def __init__(self):
self.pq = []
def add(self, item):
heappush(self.pq, item)
def poll(self):
return heappop(self.pq)
def peek(self):
return self.pq[0]
def remove(self, item):
print "in remove"
value = self.pq.remove(item)
heapify(self.pq)
return value is not None
def __len__(self):
return len(self.pq)
def inversion(puzzle):
noInversion = 0;
for z in puzzle:
j = puzzle.index(z)+1
for i in range(j,9):
if puzzle[i] == 0:
continue
if puzzle[i] < z:
noInversion+=1
j+=1
print "# of Inversions : ",noInversion
return noInversion
if __name__ == '__main__':
puzzle = range(9)
shuffle(puzzle)
while inversion(puzzle)%2 !=0:
print "Generated state cannot reach the goal state"
print "Generating new state"
shuffle(puzzle)
print puzzle
start = time.time()
solver = Solver(puzzle)
solver.solve()
end = time.time()
print 'Time Taken %2.f Seconds' % float(end - start)