import networkx as nx
rocky, wet, narrow = 0, 1, 2
torch, gear, neither = 0, 1, 2
valid_items = {rocky: (torch, gear), wet: (gear, neither), neither: (torch, neither)}
valid_regions = {torch: (rocky, narrow), gear: (rocky, wet), neither: (wet, narrow)}
def get_cave(file):
return 9171, tuple([7,721])
def generate_grid(depth, corner):
# (x, y) -> geologic index, erosion level, risk
grid = {}
for y in range(0, corner[1] + 1):
for x in range(0, corner[0] + 1):
if (x, y) in [(0, 0), target]:
geo = 0
elif x == 0:
geo = y * 48271
elif y == 0:
geo = x * 16807
else:
geo = grid[(x-1, y)][1] * grid[(x, y-1)][1]
ero = (geo + depth) % 20183
risk = ero % 3
grid[(x, y)] = (geo, ero, risk)
return grid
def dijkstra(grid, corner, target):
graph = nx.Graph()
for y in range(0, corner[1] + 1):
for x in range(0, corner[0] + 1):
items = valid_items[grid[(x, y)]]
graph.add_edge((x, y, items[0]), (x, y, items[1]), weight=7)
for dx, dy in ((0, 1), (0, -1), (1, 0), (-1, 0)):
new_x, new_y = x+dx, y+dy
if 0 <= new_x <= corner[0] and 0 <= new_y <= corner[1]:
new_items = valid_items[grid[(new_x, new_y)]]
for item in set(items).intersection(set(new_items)):
graph.add_edge((x, y, item), (new_x, new_y, item), weight=1)
return nx.dijkstra_path_length(graph, (0, 0, torch), (target[0], target[1], torch))
depth, target = get_cave("./input.txt")
grid = generate_grid(depth, target)
print("Answer 1:", sum([v[2] for v in grid.values()]))
corner = (target[0] + 100, target[1] + 100)
grid = {c: v[2] for c, v in (generate_grid(depth, corner)).items()}
print("Answer 2:", dijkstra(grid, corner, target))