Okay so basically I’m trying to do a depth-first search for a mini-peg solitaire game. For those unfamiliar with the game it’s pretty simple.
There’s a board with 10 holes and 9 pegs, a peg is represented by a 1 and an empty spot by a 0. You can move a peg backwards or forwards two holes at a time (but you can only move to an empty hole), and if you jump over another peg in the process you take it out and it becomes a hole.
So here’s what a game looks like:
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1]
[1, 1, 1, 0, 0, 1, 1, 1, 1, 1]
[1, 0, 0, 1, 0, 1, 1, 1, 1, 1]
[1, 0, 0, 1, 1, 0, 0, 1, 1, 1]
[1, 0, 0, 0, 0, 1, 0, 1, 1, 1]
[1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1, 0, 1] #etc until only 1 peg left
So, I have a generator function here that finds all legal moves for a certain “node”, or a game board:
def succ(self, node):
size = len(node)
# find all legal moves going forward
for pos in range(0, size-1):
new_node = list(node)
if ((node[pos] == 1) and (pos < (size - 2)) and (node[pos+2] == 0)):
new_node[pos] = 0 # we're moving now
new_node[pos+2] = 1 # this is where we're moving the peg to
new_node[pos+1] = 0 # take out the peg here if there was one
yield new_node
# find all legal moves going backwards
for pos in range(0, size-1):
new_node = list(node)
if ((node[pos] == 1) and (pos > 1) and (node[pos-2] == 0)):
new_node[pos] = 0 # we're moving now
new_node[pos-2] = 1 # this is where we're moving the peg
new_node[pos-1] = 0 # take out the peg here if there was one
yield new_node
Now if you know depth-first search, this seems like a GREAT generator to use when solving this puzzle. Or is it? (I think it is, maybe you can help come up with a more Pythonic way?)
Well, my recursive puzzle solver function that will use the generator isn’t working, maybe you can help me out?
def goal(self, node):
pegs = 0
for pos in node:
if pos == 1:
pegs += 1
return (pegs == 1) # returns True if there is only 1 peg
def solve_board(dfs_obj, node):
if goal(node): # only 1 peg!
print node
return node
for new_node in succ(node):
print new_node
return solve_board(new_node)
if __name__ == "__main__":
solve_board([1, 1, 1, 1, 1, 0, 1, 1, 1, 1])
So basically I think my succ() function is doing the right thing (maybe it’s not?), but my solve_board() recursion might be funky, because the board doesn’t solve.
Since you are allowed to jump over empty holes, you’ll have to keep track of any nodes you have already visited. Otherwise you will have an infinite loop.
You also need to not shortcircuit the for loop unless you have found a goal
You have the range wrong in your succ function too, you should not subtrace 1 from the size for the range. You could also rewrite it like this to remove one of the conditions from the
ifAnother way to write the succ funtion would be
This tunes the depth first slightly by preferring moves that remove a peg