Besides exceeding the maximum recursion depth, I think your implementation can also generate an infinite loop. Since the values list area is localized for each to_tree call, a central place to search does not exist if the state has already been visited. Here's a stack-based iteration example using the bit representation for the puzzle state set to an integer 4 * 9 = 36 bits. For instance:
123 456 780
Will be presented as:
0001 0010 0011 0100 0101 0110 0111 1000 0000
But connected together in the opposite direction:
0| 8| 7| 6| 5| 4| 3| 2| 1 0000 1000 0111 0110 0101 0100 0011 0010 0001 0b000010000111011001010100001100100001 => 2271560481 initialState() => 2271560481
Add some functions to create and display state:
from sys import stdout def showState(state): mask = 15 for i in xrange(9): if i % 3 == 0 and i > 0: stdout.write("\n") stdout.write(str((state & mask) >> 4 * i)) mask = mask << 4 stdout.write("\n") def makeState(arr): state = 0 for i in xrange(9): state = state | (arr[i] << 4 * i) return state def initialState(): return makeState([1,2,3,4,5,6,7,8,0])
Now we need to find the zero index:
def findZero(state): mask = 15 i = 0 while mask & state: mask = mask << 4 i = i + 1 return i
And move the adjacent number to the cell with zero:
def move(state, fromIdx, toIdx): x = (state & (15 << 4 * fromIdx)) >> 4 * fromIdx state = state & (2**36 - 1 ^ (15 << 4 * fromIdx) ^ (15 << 4 * toIdx)) state = state | (x << 4 * toIdx) return state def moves(idx):
Add a new version of the Node class you're working with:
class Node(object): def __init__(self, state, parent=None): self.parent = parent self.state = state self.children = [] def append(self, obj): self.children.append(obj)
Define the root and the states_to_nodes global object that will display the states you visited in the Node that contains this state as a value:
root = Node(initialState()) states_to_nodes = {initialState(): root}
The stack based iteration is performed here, which avoids the error of the maximum recursion depth:
stack = [root] while stack: node = stack.pop() zero_index = findZero(node.state) for i in moves(zero_index): maybe_new_state = move(node.state, i, zero_index) if not maybe_new_state in states_to_nodes: new_node = Node(maybe_new_state) states_to_nodes[maybe_new_state] = new_node node.append(new_node) stack.append(new_node) else: node.append(states_to_nodes[maybe_new_state])
Output:
example_state = makeState([5,1,3,8,6,0,2,7,4]) print "Example state:\n" showState(example_state) print "\nChildren states:\n" for child in states_to_nodes[example_state].children: showState(child.state) print """ Example state: 513 860 274 Children states: 510 863 274 513 806 274 513 864 270 """