-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhamiltonian_path.py
107 lines (84 loc) · 2.91 KB
/
hamiltonian_path.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
def insert_neighbors(x, n, m):
"""Inserts neighboring positions of x into a list."""
neighbors = []
# Check if there's a position on the right
if (x % n) + 1 < n:
neighbors.append(x + 1)
# Check if there's a position on the left
if (x % n) - 1 >= 0:
neighbors.append(x - 1)
# Check if there's a position above
if x - n >= 0:
neighbors.append(x - n)
# Check if there's a position below
if x + n <= n * m - 1:
neighbors.append(x + n)
return neighbors
def search_hamiltonian_path(graph, path, pos):
"""Recursively searches for a Hamiltonian path in the graph."""
if pos == len(graph):
if path[0] in graph[path[pos - 1]]:
return True
else:
return False
for neighbor in graph[path[pos - 1]]:
if neighbor not in path:
path[pos] = neighbor
if search_hamiltonian_path(graph, path, pos + 1):
return True
path[pos] = -1
return False
def hamiltonian_path(start, width, height):
"""Finds a Hamiltonian path starting from the given position in a grid."""
graph = [insert_neighbors(i, width, height) for i in range(width * height)]
path = [-1] * (width * height)
path[0] = start[0] + start[1] * width
if search_hamiltonian_path(graph, path, 1):
return path
return None
def hamiltonian_path_snake(matrix, n, m):
"""Finds a Hamiltonian path for a snake-like pattern in a grid."""
if n % 2 == 1 and m % 2 == 1:
return None
num_positions = n * m
path = [-1] * num_positions
path[0] = 0
# Set the default one, the first column which will point to (0, 0) position
for i in range(num_positions - 1, num_positions - m, -1):
path[i] = n * (m - (i % m))
remaing_index = num_positions - m
start_x = 1
start_y = m - 1
if m % 2 == 1:
while start_x != n:
path[remaing_index] = start_x + (start_y * n)
remaing_index -= 1
if start_y == m - 1:
start_y -= 1
else:
start_y += 1
path[remaing_index] = start_x + (start_y * n)
remaing_index -= 1
start_x += 1
start_x = n - 1
else:
while start_x != n - 1:
path[remaing_index] = start_x + (start_y * n)
remaing_index -= 1
start_x += 1
path[remaing_index] = start_x + (start_y * n)
remaing_index -= 1
start_y -= 1
direction = -1 # Go from right to left, then reverse the direction
while start_y != -1:
while start_x != 0 and start_x != n:
path[remaing_index] = start_x + (start_y * n)
remaing_index -= 1
start_x += direction
if direction == -1:
start_x = 1
else:
start_x = n - 1
start_y -= 1
direction *= -1
return path