-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathknight_tour_warnsdorf.py
67 lines (44 loc) · 1.86 KB
/
knight_tour_warnsdorf.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
"""Solution of Knight tour problem using Warnsdorf's rule."""
import sys
sys.setrecursionlimit(10000) # use this for larger values of N
N = 8
x_initial, y_initial = 0, 0
def is_safe(board, x, y):
return 0 <= x < N and 0 <= y < N and board[x][y] == -1
def solve_tour():
"""Function to find one of the feasible knight tours."""
board = [[-1 for _ in range(N)] for _ in range(N)]
board[x_initial][y_initial] = 0
# all 8 possible moves of knight at any given position
jumps = ((-1, 2), (1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1))
z = find_tour(board, x_initial, y_initial, 1, jumps)
if not z:
print("No solution exist!")
def find_tour(board, x, y, move_k, jumps):
"""Recursive function that return whether a solution exist from the given position."""
if move_k == N * N:
for i in range(N):
for j in range(N):
print("%3d" % board[i][j], end=" ")
print()
return True
sorted_moves = min_degree(board, x, y, jumps)
for x_next, y_next in sorted_moves:
board[x_next][y_next] = move_k
if find_tour(board, x_next, y_next, move_k + 1, jumps):
return True
board[x_next][y_next] = -1 # backtrack
return False
def min_degree(board, x, y, jumps):
"""Function that return the list of sorted moves in increasing order of degree."""
empty_neighbours = []
for jump in jumps:
x_next = x + jump[0]
y_next = y + jump[1]
if is_safe(board, x_next, y_next):
empty_neighbours.append([x_next, y_next])
sorted_moves = sorted(empty_neighbours, key=lambda c: sum(
[is_safe(board, c[0] + j[0], c[1] + j[1]) for j in jumps]))
return sorted_moves
if __name__ == "__main__":
solve_tour()