Solve 2018 day 22 and 2019 day 20
This commit is contained in:
89
2018/d22.py
Normal file
89
2018/d22.py
Normal 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)
|
||||
Reference in New Issue
Block a user