Solve 2018 day 22 and 2019 day 20

This commit is contained in:
felixm 2024-09-21 22:49:45 -04:00
parent db383c7cfa
commit 6c3aec3d6e
4 changed files with 251 additions and 4 deletions

89
2018/d22.py Normal file
View File

@ -0,0 +1,89 @@
from lib import get_data, str_to_ints, A_Star
data = get_data(__file__)
depth, x_target, y_target = str_to_ints(data)
# depth, x_target, y_target = 510, 10, 10
# depth, x_target, y_target = 9171, 7, 721
# print(depth, x_target, y_target)
x_area_max = x_target * 10
y_area_max = y_target * 10
maze = [[None for _ in range(x_area_max + 1)] for _ in range(y_area_max + 1)]
maze[0][0] = 0
maze[y_target][x_target] = 0
mod = 20183
for x in range(x_area_max + 1):
maze[0][x] = x * 16807 % mod
for y in range(y_area_max + 1):
maze[y][0] = y * 48271 % mod
for y in range(1, y_area_max + 1):
for x in range(1, x_area_max + 1):
if x == x_target and y == y_target:
continue
assert maze[y][x] is None
geo_index = ((maze[y][x - 1] + depth) * (maze[y - 1][x] + depth)) % mod
maze[y][x] = geo_index
t = 0
for y in range(y_target + 1):
for x in range(x_target + 1):
t += ((maze[y][x] + depth) % mod) % 3
print(t)
for y in range(y_area_max + 1):
for x in range(x_area_max + 1):
maze[y][x] = ((maze[y][x] + depth) % mod) % 3
def allowed(area, tool):
# 0 = rocky, 1 = wet, 2 = narrow
# 0 = torch, 1 = climbing, 2 = neither
return (
(area == 0 and (tool in [0, 1]))
or (area == 1 and (tool in [1, 2]))
or (area == 2 and (tool in [0, 2]))
)
def neighbors(state):
x, y, tool = state
r = []
area = maze[y][x]
for t in range(3):
if allowed(area, t) and t != tool:
r.append((x, y, t))
for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
nx, ny = x + dx, y + dy
if not (nx >= 0 and nx < x_area_max and ny >= 0 and ny < y_area_max):
continue
if not allowed(maze[ny][nx], tool):
continue
r.append((nx, ny, tool))
return r
def distance(a, b):
if a == 0:
return 0
elif a[2] != b[2]:
assert a[0] == b[0] and a[1] == b[1]
return 7
else:
return 1
a = A_Star(
starts=[(0, 0, 0)],
is_goal=lambda s: s[0] == x_target and s[1] == y_target and s[2] == 0,
h=lambda s: abs(s[0] - x_target) + abs(s[1] - y_target),
d=distance,
neighbors=neighbors,
)
print(a.cost)

154
2019/d20.py Normal file
View File

@ -0,0 +1,154 @@
from lib import get_data, Grid2D, LETTERS_UPPER
from collections import defaultdict
data = get_data(__file__)
g = Grid2D(data)
start = None
end = None
warps = defaultdict(list)
inner = set()
outer = set()
for row in range(g.n_rows - 2):
for col in range(g.n_cols - 2):
a, b, c = g[(row, col)], g[(row, col + 1)], g[(row, col + 2)]
x, y, z = g[(row, col)], g[(row + 1, col)], g[(row + 2, col)]
if a in LETTERS_UPPER and b in LETTERS_UPPER and c == ".":
warps[a + b].append((row, col + 2))
if col == 0:
outer.add((row, col + 2))
else:
inner.add((row, col + 2))
elif a == "." and b in LETTERS_UPPER and c in LETTERS_UPPER:
warps[b + c].append((row, col))
if col + 3 == g.n_cols:
outer.add((row, col))
else:
inner.add((row, col))
if x in LETTERS_UPPER and y in LETTERS_UPPER and z == ".":
if x + y == "AA":
start = (row + 2, col)
else:
warps[x + y].append((row + 2, col))
if row == 0:
outer.add((row + 2, col))
else:
inner.add((row + 2, col))
elif x == "." and y in LETTERS_UPPER and z in LETTERS_UPPER:
if y + z == "ZZ":
end = (row, col)
else:
warps[y + z].append((row, col))
if row + 3 == g.n_rows:
outer.add((row, col))
else:
inner.add((row, col))
graph = defaultdict(list)
allnodes = set([start, end])
for key, (a, b) in warps.items():
graph[a].append((b, 1))
graph[b].append((a, 1))
allnodes.add(a)
allnodes.add(b)
for startnode in allnodes:
to_visit = [startnode]
steps = 0
seen = set()
while to_visit:
steps += 1
new_to_visit = []
for node in to_visit:
if node in seen:
continue
else:
seen.add(node)
assert node is not None
for nb in g.neighbors_ort(node):
if nb in seen:
continue
if nb in allnodes:
if not (nb, steps) in graph[startnode]:
graph[startnode].append((nb, steps))
if not (startnode, steps) in graph[nb]:
graph[nb].append((startnode, steps))
seen.add(nb)
elif g[nb] == ".":
new_to_visit.append(nb)
to_visit = new_to_visit
shortest = {start: 0}
to_visit = [start]
seen = set()
while to_visit:
to_visit.sort(key=lambda node: shortest[node], reverse=True)
current = to_visit.pop()
if current in seen:
continue
else:
seen.add(current)
for nb, dist in graph[current]:
new_dist = shortest[current] + dist
if not nb in shortest:
shortest[nb] = new_dist
elif new_dist < shortest[nb]:
shortest[nb] = new_dist
if nb not in seen:
to_visit.append(nb)
print(shortest[end])
shortest = {(start, 0): 0}
to_visit = [(start, 0)]
seen = set()
while to_visit:
to_visit.sort(key=lambda node: shortest[node], reverse=True)
current, level = to_visit.pop()
if (current, level) in seen:
continue
else:
seen.add((current, level))
for nb, dist in graph[current]:
new_dist = shortest[(current, level)] + dist
if nb == end and level == 0:
print(new_dist)
to_visit = None
break
elif nb == end:
continue
elif nb == start:
continue
if dist == 1:
if current in inner:
new_level = level + 1
elif current in outer:
new_level = level - 1
else:
assert False
else:
new_level = level
if new_level < 0:
continue
nn = (nb, new_level)
if not nn in shortest:
shortest[nn] = new_dist
elif new_dist < shortest[nn]:
shortest[nn] = new_dist
to_visit.append(nn)

View File

@ -109,7 +109,8 @@ Solutions and utility script for Advent of Code challenges in Python.
- Day 19: days, super fun, but hard for me - Day 19: days, super fun, but hard for me
- Day 20: - Day 20:
- Day 21: 28:40 (16th - brute force but still not so bad) - Day 21: 28:40 (16th - brute force but still not so bad)
- Day 22: - Day 22: 185:00 (should not have been so slow but was fun)
- Day 23:
## AoC 2019 ## AoC 2019
@ -131,8 +132,9 @@ Solutions and utility script for Advent of Code challenges in Python.
- Day 16: days (Wow. Just too hard for me to solve quickly?) - Day 16: days (Wow. Just too hard for me to solve quickly?)
- Day 17: days (Fun but too tricky for me to be fast.) - Day 17: days (Fun but too tricky for me to be fast.)
- Day 18: days (Slow and slow algorithm.) - Day 18: days (Slow and slow algorithm.)
- Day 19: 40:00 (Way too slow! Oversight error. Come on.) - Day 19: 40:00 (Way too slow! Oversight error. Come on.)
- Day 20: - Day 20: days (Not actually that hard but I struggled for no reason.)
- Day 21:
## AoC 2020 ## AoC 2020

4
lib.py
View File

@ -229,6 +229,7 @@ class A_Star(object):
""" """
open_set = [] open_set = []
g_score = {} g_score = {}
self.cost = None
for start in starts: for start in starts:
heapq.heappush(open_set, (h(start), start)) heapq.heappush(open_set, (h(start), start))
@ -237,7 +238,8 @@ class A_Star(object):
while open_set: while open_set:
current_f_score, current = heapq.heappop(open_set) current_f_score, current = heapq.heappop(open_set)
if is_goal(current): if is_goal(current):
self.cost = current_f_score assert current_f_score == g_score[current]
self.cost = g_score[current]
break break
for neighbor in neighbors(current): for neighbor in neighbors(current):