79 lines
1.9 KiB
Python
79 lines
1.9 KiB
Python
from helpers import *
|
|
lines = read_day(24).split('\n')[1:-1] # strip walls
|
|
sample_lines = '''
|
|
#.######
|
|
#>>.<^<#
|
|
#.<..<<#
|
|
#>v.><>#
|
|
#<^v^^>#
|
|
######.#'''.strip().split('\n')[1:-1]
|
|
|
|
def sim(lines):
|
|
height = len(lines)
|
|
width = len(lines[0]) - 2
|
|
blizzards_left = set()
|
|
blizzards_right = set()
|
|
blizzards_up = set()
|
|
blizzards_down = set()
|
|
for row, line in enumerate(lines):
|
|
for col, c in enumerate(line[1:-1]): # strip walls
|
|
if c == '<':
|
|
blizzards_left.add((col, row))
|
|
elif c == '>':
|
|
blizzards_right.add((col, row))
|
|
elif c == '^':
|
|
blizzards_up.add((col, row))
|
|
elif c == 'v':
|
|
blizzards_down.add((col, row))
|
|
|
|
def position_free(col: int, row: int, time: int) -> bool:
|
|
if ((col+time)%width, row) in blizzards_left:
|
|
return False
|
|
if ((col-time)%width, row) in blizzards_right:
|
|
return False
|
|
if (col, (row+time)%height) in blizzards_up:
|
|
return False
|
|
if (col, (row-time)%height) in blizzards_down:
|
|
return False
|
|
return True
|
|
|
|
seen_states = set()
|
|
state_stack = [(0,-1,0)]
|
|
def try_add_state(col: int, row: int, time: int):
|
|
if col < 0 or col >= width or row < -1 or row >= height:
|
|
return
|
|
if row == -1 and col != 0:
|
|
return
|
|
if not position_free(col, row, time):
|
|
return
|
|
triple = (col, row, time)
|
|
if triple not in seen_states:
|
|
seen_states.add(triple)
|
|
state_stack.append(triple)
|
|
|
|
best_time = None
|
|
goal = (width-1, height)
|
|
|
|
while state_stack:
|
|
col, row, t = state_stack.pop()
|
|
t1 = t + 1
|
|
goal_distance = goal[0]-col + goal[1]-row # Manhattan distance
|
|
if goal_distance == 1: # we're right next to the goal! move there and end this trail
|
|
if best_time:
|
|
best_time = min(best_time, t1)
|
|
else:
|
|
best_time = t1
|
|
continue
|
|
if best_time and (t + goal_distance > best_time):
|
|
continue
|
|
try_add_state(col, row, t1)
|
|
try_add_state(col-1, row, t1)
|
|
try_add_state(col, row-1, t1)
|
|
try_add_state(col+1, row, t1)
|
|
try_add_state(col, row+1, t1)
|
|
|
|
return best_time
|
|
|
|
print(sim(sample_lines))
|
|
print(sim(lines))
|