-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday20.py
More file actions
152 lines (135 loc) · 5.26 KB
/
day20.py
File metadata and controls
152 lines (135 loc) · 5.26 KB
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import numpy as np
with open('/Users/relyea/data/input.txt') as input_file:
inpstring = input_file.readlines()
# once you have those, for every period, find all paths to all other periods using bloop
# then just do a simple traversal, but if you find a loop, throw it out
themaze_list = []
for iline, line in enumerate(inpstring):
newline = [a for a in line.strip('\n')]
themaze_list.append(newline)
themaze = np.array(themaze_list)
y1 = 2
y2 = themaze.shape[1] - 3
x1 = 2
x2 = themaze.shape[0] - 3
boundary_points_to_names = {}
boundary_names_to_points = {}
def fill_exit_dicts(point, name, edge):
boundary_points_to_names[point] = (name, edge)
if name not in boundary_names_to_points:
boundary_names_to_points[name] = [(point, edge)]
else:
boundary_names_to_points[name].append((point, edge))
return
INNER = 1
OUTER = 0
for ii in range(x1, x2+1):
if themaze[ii, y1] == '.':
point = (ii, y1)
name = ''.join(themaze[ii, 0:2])
fill_exit_dicts(point, name, OUTER)
if themaze[ii, y2] == '.':
point = (ii, y2)
name = ''.join(themaze[ii, y2+1:])
fill_exit_dicts(point, name, OUTER)
for jj in range(y1, y2+1):
if themaze[x1, jj] == '.':
point = (x1, jj)
name = ''.join(themaze[0:2, jj])
fill_exit_dicts(point, name, OUTER)
if themaze[x2, jj] == '.':
point = (x2, jj)
name = ''.join(themaze[x2+1:, jj])
fill_exit_dicts(point, name, OUTER)
space_coords = np.where(themaze[2:-2,2:-2] == ' ')
x3 = space_coords[0][0]+2
x4 = space_coords[0][-1]+2
y3 = space_coords[1][0]+2
y4 = space_coords[1][-1]+2
for ii in range(x3,x4):
if themaze[ii, y3-1] == '.':
point = (ii, y3-1)
name = ''.join(themaze[ii, y3:y3+2])
fill_exit_dicts(point, name, INNER)
if themaze[ii, y4+1] == '.':
point = (ii, y4+1)
name = ''.join(themaze[ii, y4-1:y4+1])
fill_exit_dicts(point, name, INNER)
for jj in range(y3,y4):
if themaze[x3-1, jj] == '.':
point = (x3-1, jj)
name = ''.join(themaze[x3:x3+2, jj])
fill_exit_dicts(point, name, INNER)
if themaze[x4+1, jj] == '.':
point = (x4+1, jj)
name = ''.join(themaze[x4-1:x4+1, jj])
fill_exit_dicts(point, name, INNER)
def get_neighbors(point):
return [(point[0],point[1]+1),(point[0],point[1]-1),(point[0]-1,point[1]),(point[0]+1,point[1])]
def is_in_maze(point):
if (
point[0] < x1 or
point[0] > x2 or
point[1] < y1 or
point[1] > y2
):
return False
else:
return True
point_to_point_distance_map = {}
for entrancepoint in boundary_points_to_names:
(entrancename, entranceedge) = boundary_points_to_names[entrancepoint]
# print(entrancename)
if (entrancename, entranceedge) not in point_to_point_distance_map:
point_to_point_distance_map[(entrancename, entranceedge)] = []
slurm_list = [entrancepoint]
totaldistance = 0
current_iteration = [entrancepoint]
while current_iteration != []:
new_current_iteration = []
totaldistance += 1
# print(totaldistance)
for point in current_iteration:
neighbors = get_neighbors(point)
valid_neighbors = [neighbor for neighbor in neighbors if is_in_maze(neighbor) and themaze[neighbor] == '.' and neighbor not in slurm_list]
for neighbor in valid_neighbors:
slurm_list.append(neighbor)
new_current_iteration.append(neighbor)
if neighbor in boundary_points_to_names:
(name, edge) = boundary_points_to_names[neighbor]
point_to_point_distance_map[(entrancename, entranceedge)].append([name,edge,totaldistance])
current_iteration = new_current_iteration
start = 'AA'
def find_distance_to_neighbors(distance, point, edge, layer, points_already_visited):
current_best = 10000
current_found = False
best_points_visited = []
# print(distance, point, edge, layer, points_already_visited, 'START')
for (neighbor,newedge,newdistance) in point_to_point_distance_map[(point,edge)]:
# print(neighbor, newedge, newdistance,'NEIGHBOR')
if neighbor == 'AA':
continue
elif neighbor == 'ZZ':
if layer != 0:
continue
else:
if distance + newdistance < current_best:
return True, distance + newdistance, points_already_visited
elif layer == 0 and newedge == OUTER:
continue
elif (neighbor, layer) not in points_already_visited:
if newedge == INNER:
newlayer = layer + 1
if newlayer > 30:
continue
else:
newlayer = layer - 1
if newlayer < 0:
continue
wasfound, found_distance, visitlist = find_distance_to_neighbors(distance + newdistance + 1, neighbor, 1-newedge, newlayer, points_already_visited + [(neighbor, layer)])
if wasfound and found_distance < current_best:
current_best = found_distance
current_found = True
best_points_visited = visitlist
return current_found, current_best, best_points_visited
find_distance_to_neighbors(0, 'AA', OUTER, 0, [])