-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathedgemaze.py
77 lines (59 loc) · 2.48 KB
/
edgemaze.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
import math
import numpy
arrow_directions = {b'>': (0, -1), b'v': (-1, 0), b'<': (0, 1), b'^': (1, 0)}
class Solver:
def __init__(self, maze):
self.maze = maze
self.distances = numpy.full_like(maze, -1, int)
self.distances[maze & 1 == 1] = 0
self.directions = numpy.full_like(maze, b' ', ('a', 1))
self.directions[maze & 1 == 1] = "X"
self.starting_points = maze & 1
self.is_reachable = False
def solve(self):
start_points = numpy.where(self.starting_points == 1)
if start_points:
to_test = list(zip(start_points[0], start_points[1]))
to_test_set = set(zip(start_points[0], start_points[1]))
while to_test:
expanding = to_test.pop(0)
to_test_set.remove(expanding)
distance = self.distances[expanding]
for arrow, direction in arrow_directions.items():
adjacent = tuple(map(numpy.add, expanding, direction))
if (self.can_go_there(expanding, adjacent) and
adjacent not in to_test_set
and self.distances[adjacent] == -1):
to_test.append(adjacent)
to_test_set.add(adjacent)
self.directions[adjacent] = arrow
self.distances[adjacent] = distance+1
self.is_reachable = not numpy.any(self.distances == -1)
def path(self, row, collumn):
path = []
current = (row, collumn)
if self.distances[current] == -1:
raise ValueError("Nirvana is not reachable you know")
while self.distances[current] > 0:
path.append(current)
arrow = self.directions[current]
direction = tuple(map(lambda num: -1*num, arrow_directions[arrow]))
next = tuple(map(numpy.add, current, direction))
current = next
path.append(current)
return path
def can_go_there(self, expanding, adjacent):
if self.coord_valid(*adjacent):
for i in range(2):
if expanding[i] != adjacent[i]:
return self.maze[max(adjacent, expanding, key=lambda item: item[i])] & (4 - 2*i) == 0
else:
return False
def coord_valid(self, y, x):
return 0 <= y < self.maze.shape[0] and 0 <= x < self.maze.shape[1]
def analyze(maze):
if maze.ndim != 2:
raise TypeError("dimension mansion")
solver = Solver(maze)
solver.solve()
return solver