Files
aocpy/2018/d22.py

90 lines
2.2 KiB
Python

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)