Subversion Repositories programming

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
385 ira 1
#!/usr/bin/env python
2
 
3
__author__    = "Ira W. Snyder (devel@irasnyder.com)"
4
__copyright__ = "Copyright (c) 2006 Ira W. Snyder (devel@irasnyder.com)"
5
__license__   = "GNU GPL v2 (or, at your option, any later version)"
6
 
398 ira 7
from PyCompat import * # fixes for school computers
8
 
397 ira 9
class PuzzlePiece (object):
385 ira 10
 
11
	EMPTY = 'E'
395 ira 12
	(UP, DOWN, LEFT, RIGHT) = ('up', 'down', 'left', 'right')
13
 
14
	def __init__ (self, state, depth=0, goal=None, generated_by='root'):
393 ira 15
		if len(state) != 9:
16
			raise ValueError
17
 
385 ira 18
		self.state = state
393 ira 19
		self.depth = depth
20
		self.goal = goal
395 ira 21
		self.generated_by = generated_by
385 ira 22
 
23
	def __eq__ (self, rhs):
24
		return self.state == rhs.state
25
 
26
	def __repr__(self):
27
		"""Print yourself"""
28
		result = ''
29
		for i in xrange(3):
30
			result += '%s %s %s' % (self.state[3*i], self.state[3*i+1], self.state[3*i+2])
31
			if i<2:
32
				result += '\n'
33
 
34
		return result
35
 
36
	def get_children (self):
37
		children = []
393 ira 38
		empty_pos = self.find_position (self.EMPTY)
385 ira 39
 
40
		# Get the correct moves for this position
395 ira 41
		mov = {	0 : (self.DOWN,  self.RIGHT),
42
			1 : (self.DOWN,  self.LEFT,  self.RIGHT),
43
			2 : (self.DOWN,  self.LEFT),
44
			3 : (self.DOWN,  self.RIGHT, self.UP),
45
			4 : (self.DOWN,  self.LEFT,  self.RIGHT, self.UP),
46
			5 : (self.DOWN,  self.LEFT,  self.UP),
47
			6 : (self.RIGHT, self.UP),
48
			7 : (self.LEFT,  self.RIGHT, self.UP),
49
			8 : (self.LEFT,  self.UP) }[empty_pos]
385 ira 50
 
51
		# Call each of the proper functions
395 ira 52
		for m in mov:
53
			config = self.move (empty_pos, m)
54
			children.append (PuzzlePiece (config, self.depth+1, self.goal, m))
385 ira 55
 
56
		# Return the created list
57
		return children
58
 
393 ira 59
	def find_position (self, value):
385 ira 60
		for i in xrange (len (self.state)):
393 ira 61
			if self.state[i] == value:
385 ira 62
				return i
63
 
64
		raise ValueError
395 ira 65
	def move (self, empty_pos, direction):
66
		val = 0
385 ira 67
 
395 ira 68
		if direction == self.UP:
69
			val = -3
70
		elif direction == self.LEFT:
71
			val = -1
72
		elif direction == self.RIGHT:
73
			val = 1
74
		elif direction == self.DOWN:
75
			val = 3
76
		else:
77
			raise ValueError
385 ira 78
 
79
		copy = self.state[:]
395 ira 80
		copy[empty_pos] = copy[empty_pos + val]
81
		copy[empty_pos + val] = self.EMPTY
385 ira 82
		return copy
83
 
393 ira 84
	def num_out_of_place (self):
85
		"""Find the number of tiles that are out of place"""
86
		count = 0
385 ira 87
 
393 ira 88
		for i in xrange(len(self.state)):
89
			if self.state[i] != self.goal.state[i]:
90
				count += 1
385 ira 91
 
393 ira 92
		return count
385 ira 93
 
393 ira 94
	def total_distance_from_correct (self):
95
		"""Find the total distance that every piece of myself is from
96
		the goal configuration given."""
97
		total = 0
98
 
99
		for e in self.state:
100
			mypos = self.find_position (e)
101
			goalpos = self.goal.find_position (e)
102
 
103
			total += self.distance_from_correct (mypos, goalpos)
104
 
105
		return total
106
 
107
 
108
	def distance_from_correct (self, mypos, goalpos):
109
		"""Find a single piece's distance from the correct position."""
110
		crmap={	0 : (0, 0),
111
			1 : (0, 1),
112
			2 : (0, 2),
113
			3 : (1, 0),
114
			4 : (1, 1),
115
			5 : (1, 2),
116
			6 : (2, 0),
117
			7 : (2, 1),
118
			8 : (2, 2) }
119
 
120
		myrow, mycol = crmap[mypos]
121
		goalrow, goalcol = crmap[goalpos]
122
 
123
		return (abs(myrow - goalrow) + abs(mycol - goalcol))
124
 
125
def main ():
126
	initial = [1, 2, 3, 4, 5, 6, 7, 8, 'E']
127
	g = PuzzlePiece ([1, 7, 3, 4, 5, 6, 2, 8, 'E'])
128
	p = PuzzlePiece (initial, 0, g)
129
 
130
	print 'out of place:', p.num_out_of_place ()
131
	print 'dist:', p.total_distance_from_correct ()
132
 
133
if __name__ == '__main__':
134
	main ()
135