Files
advent-of-code-2023/day_17/part2.py

60 lines
2.5 KiB
Python

def test(input, solution):
# print(f"Running input {input}")
result = process(input)
print(f"Solution was {result}")
assert result == solution
def run():
file = open("input.txt", "r")
return process(file.read()[:-1])
def neighbors(node, height, width):
(down, right) = node
current_neighbors = [("D", (down+1, right)), ("U", (down-1, right)), ("R", (down, right+1)), ("L", (down, right-1))]
if down == 0:
current_neighbors.remove(("U", (down-1, right)))
if down == height:
current_neighbors.remove(("D", (down+1, right)))
if right == 0:
current_neighbors.remove(("L", (down, right-1)))
if right == width:
current_neighbors.remove(("R", (down, right+1)))
return current_neighbors
def dijkstra(input):
down = len(input.split("\n")) - 1
right = len(input.split("\n")[0]) - 1
unvisited_nodes = {}
visited_nodes = {}
current_node = (0, 0, 0, 0) # x, y, direction of last move x, direction of last move y
unvisited_nodes[0, 0, 0, 0] = 0
# This is genius. Shamelessly stolen. Easy bounds checking by making a dict of indices -> scores
board = { (i,j): int(cell) for i,row in enumerate(input.split('\n')) for j,cell in enumerate(row) }
while unvisited_nodes:
current_node = sorted(unvisited_nodes.items(), key=lambda item: item[1])[0][0]
(x,y,dx_last,dy_last) = current_node
current_score = unvisited_nodes[current_node]
del unvisited_nodes[current_node]
if current_node[0] == down and current_node[1] == right: return current_score
if current_node in visited_nodes: continue
visited_nodes[current_node] = current_score
possible_directions = {(1,0), (-1,0), (0,1), (0,-1)} - {(dx_last,dy_last), (-dx_last,-dy_last)}
for (dx, dy) in possible_directions:
new_x, new_y, new_score = x, y, current_score
for i in range(1,11):
new_x = new_x + dx
new_y = new_y + dy
if (new_x, new_y) in board:
new_score += board[new_x, new_y]
if i >= 4:
if (new_x, new_y, dx, dy) not in unvisited_nodes:
unvisited_nodes[(new_x, new_y, dx, dy)] = new_score
elif new_score < unvisited_nodes[(new_x, new_y, dx, dy)]:
unvisited_nodes[(new_x, new_y, dx, dy)] = new_score
return int("inf")
def process(input):
sol = dijkstra(input)
return sol