60 lines
2.5 KiB
Python
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
|