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