Subversion Repositories programming

Rev

Rev 397 | Go to most recent revision | Blame | Compare with Previous | 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)"

from PyCompat import * # fixes for school computers

class PuzzlePiece (object):

        EMPTY = 'E'
        (UP, DOWN, LEFT, RIGHT) = ('up', 'down', 'left', 'right')

        def __init__ (self, state, depth=0, goal=None, generated_by='root'):
                if len(state) != 9:
                        raise ValueError

                self.state = state
                self.depth = depth
                self.goal = goal
                self.generated_by = generated_by

        def __eq__ (self, rhs):
                return self.state == rhs.state

        def __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 result

        def get_children (self):
                children = []
                empty_pos = self.find_position (self.EMPTY)

                # Get the correct moves for this position
                mov = { 0 : (self.DOWN,  self.RIGHT),
                        1 : (self.DOWN,  self.LEFT,  self.RIGHT),
                        2 : (self.DOWN,  self.LEFT),
                        3 : (self.DOWN,  self.RIGHT, self.UP),
                        4 : (self.DOWN,  self.LEFT,  self.RIGHT, self.UP),
                        5 : (self.DOWN,  self.LEFT,  self.UP),
                        6 : (self.RIGHT, self.UP),
                        7 : (self.LEFT,  self.RIGHT, self.UP),
                        8 : (self.LEFT,  self.UP) }[empty_pos]

                # Call each of the proper functions
                for m in mov:
                        config = self.move (empty_pos, m)
                        children.append (PuzzlePiece (config, self.depth+1, self.goal, m))

                # Return the created list
                return children

        def find_position (self, value):
                for i in xrange (len (self.state)):
                        if self.state[i] == value:
                                return i

                raise ValueError
        def move (self, empty_pos, direction):
                val = 0

                if direction == self.UP:
                        val = -3
                elif direction == self.LEFT:
                        val = -1
                elif direction == self.RIGHT:
                        val = 1
                elif direction == self.DOWN:
                        val = 3
                else:
                        raise ValueError

                copy = self.state[:]
                copy[empty_pos] = copy[empty_pos + val]
                copy[empty_pos + val] = self.EMPTY
                return copy

        def num_out_of_place (self):
                """Find the number of tiles that are out of place"""
                count = 0

                for i in xrange(len(self.state)):
                        if self.state[i] != self.goal.state[i]:
                                count += 1

                return count

        def total_distance_from_correct (self):
                """Find the total distance that every piece of myself is from
                the goal configuration given."""
                total = 0

                for e in self.state:
                        mypos = self.find_position (e)
                        goalpos = self.goal.find_position (e)

                        total += self.distance_from_correct (mypos, goalpos)

                return total


        def 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 ()