Rev 385 | Blame | Last modification | View Log | RSS feed
#!/usr/bin/env python__author__ = "Ira W. Snyder (devel@irasnyder.com)"__copyright__ = "Copyright (c) 2006 Ira W. Snyder (devel@irasnyder.com)"__license__ = "GNU GPL v2 (or, at your option, any later version)"class PuzzlePiece (object):EMPTY = 'E'def __init__ (self, state, depth=0, goal=None):if len(state) != 9:raise ValueErrorself.state = stateself.depth = depthself.goal = goaldef __eq__ (self, rhs):return self.state == rhs.statedef __repr__(self):"""Print yourself"""result = ''for i in xrange(3):result += '%s %s %s' % (self.state[3*i], self.state[3*i+1], self.state[3*i+2])if i<2:result += '\n'return resultdef get_children (self):children = []empty_pos = self.find_position (self.EMPTY)# Get the correct moves for this positionfn = { 0 : (self.move_down, self.move_right),1 : (self.move_down, self.move_left, self.move_right),2 : (self.move_down, self.move_left),3 : (self.move_down, self.move_right, self.move_up),4 : (self.move_down, self.move_left, self.move_right, self.move_up),5 : (self.move_down, self.move_left, self.move_up),6 : (self.move_right, self.move_up),7 : (self.move_left, self.move_right, self.move_up),8 : (self.move_left, self.move_up) }[empty_pos]# Call each of the proper functionsfor f in fn:children.append (PuzzlePiece (f (empty_pos), self.depth+1, self.goal))# Return the created listreturn childrendef find_position (self, value):for i in xrange (len (self.state)):if self.state[i] == value:return iraise ValueErrordef move_up (self, empty_pos):copy = self.state[:]copy[empty_pos] = copy[empty_pos - 3]copy[empty_pos - 3] = self.EMPTYreturn copydef move_left (self, empty_pos):copy = self.state[:]copy[empty_pos] = copy[empty_pos - 1]copy[empty_pos - 1] = self.EMPTYreturn copydef move_right (self, empty_pos):copy = self.state[:]copy[empty_pos] = copy[empty_pos + 1]copy[empty_pos + 1] = self.EMPTYreturn copydef move_down (self, empty_pos):copy = self.state[:]copy[empty_pos] = copy[empty_pos + 3]copy[empty_pos + 3] = self.EMPTYreturn copydef num_out_of_place (self):"""Find the number of tiles that are out of place"""count = 0for i in xrange(len(self.state)):if self.state[i] != self.goal.state[i]:count += 1return countdef total_distance_from_correct (self):"""Find the total distance that every piece of myself is fromthe goal configuration given."""total = 0for e in self.state:mypos = self.find_position (e)goalpos = self.goal.find_position (e)total += self.distance_from_correct (mypos, goalpos)return totaldef distance_from_correct (self, mypos, goalpos):"""Find a single piece's distance from the correct position."""crmap={ 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) }myrow, mycol = crmap[mypos]goalrow, goalcol = crmap[goalpos]return (abs(myrow - goalrow) + abs(mycol - goalcol))def main ():initial = [1, 2, 3, 4, 5, 6, 7, 8, 'E']g = PuzzlePiece ([1, 7, 3, 4, 5, 6, 2, 8, 'E'])p = PuzzlePiece (initial, 0, g)print 'out of place:', p.num_out_of_place ()print 'dist:', p.total_distance_from_correct ()if __name__ == '__main__':main ()