-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathknight_tour.py
executable file
·79 lines (62 loc) · 2.4 KB
/
knight_tour.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/python
"""
http://interactivepython.org/runestone/static/pythonds/Graphs/TheKnightsTourProblem.html
A good example of DFS.
"""
from graph import Graph, Vertex
def get_cell_key(x, y, dimension):
return y*dimension + x
def generate_valid_moves_from(x, y, dimension):
valid_moves = []
deltas = ((-2, -1), (-2, 1), (2, -1), (2, 1), (-1, 2), (-1, -2), (1, -2), (1, 2))
for dx, dy in deltas:
new_x, new_y = x+dx, y+dy
if 0 <= new_x <= dimension-1 and 0 <= new_y <= dimension-1:
valid_moves.append((new_x, new_y))
return [get_cell_key(i, j, dimension) for i, j in valid_moves]
def build_graph(dimension=8):
""" Build a graph of valid knight moves. """
graph = Graph()
# Go through each cell one at a time.
for i in range(dimension):
for j in range(dimension):
cell_key = get_cell_key(i, j, dimension)
# Add the cell to the graph.
from_vertex = graph.add_vertex(cell_key)
# Figure out the valid knight moves from that cell.
valid_moves = generate_valid_moves_from(i, j, dimension)
for vm_key in valid_moves:
# Add each target cells to the graph and create an edge to represent
# the valid move.
to_vertex = graph.add_vertex(vm_key)
from_vertex.add_neighbor(to_vertex)
return graph
def knight_tour(cur_path_len, path, to_visit, target_path_len):
done = False
to_visit.color = Vertex.GRAY
path.append(to_visit)
cur_path_len += 1
print "Current vertex {0}".format(to_visit.key)
print "Current path length {0}".format(cur_path_len)
if cur_path_len == target_path_len:
print "DONE"
done = True # we found a solution
else:
for neighbor in to_visit.neighbors:
if neighbor.color == Vertex.WHITE:
done = knight_tour(cur_path_len, path, neighbor, target_path_len)
if done:
break # we found a solution deeper in the recurrence tree
if not done: # we ran into a dead end, backtrack
print "DEAD END"
path.pop()
to_visit.color = Vertex.WHITE
return done
dimension = 5
g = build_graph(dimension)
solution_path = []
knight_tour(0, solution_path, g.vertices[0], dimension*dimension)
print
print "Solution:"
print len(solution_path)
print " ".join([str(i.key) for i in solution_path])