55 lines
2.0 KiB
Python
55 lines
2.0 KiB
Python
|
import sys
|
||
|
from collections import deque, namedtuple
|
||
|
|
||
|
MOVES = [(0, 1), (0, -1), (1, 0), (-1, 0), (0, 0)]
|
||
|
|
||
|
Blizzards = namedtuple('Blizzards', ['rows', 'cols', 'left', 'right', 'up', 'down'])
|
||
|
|
||
|
|
||
|
def is_free(blizz, r, c, t):
|
||
|
return not any((
|
||
|
(r, (c-t) % blizz.cols) in blizz.right,
|
||
|
(r, (c+t) % blizz.cols) in blizz.left,
|
||
|
((r-t) % blizz.rows, c) in blizz.down,
|
||
|
((r+t) % blizz.rows, c) in blizz.up
|
||
|
))
|
||
|
|
||
|
def parse(data):
|
||
|
lines = [l[1:-1] for l in data.splitlines()[1:-1]] # Cut off walls
|
||
|
rows, cols = len(lines), len(lines[0])
|
||
|
left = frozenset((r, c) for r in range(rows) for c in range(cols) if lines[r][c] == '<')
|
||
|
right = frozenset((r, c) for r in range(rows) for c in range(cols) if lines[r][c] == '>')
|
||
|
up = frozenset((r, c) for r in range(rows) for c in range(cols) if lines[r][c] == '^')
|
||
|
down = frozenset((r, c) for r in range(rows) for c in range(cols) if lines[r][c] == 'v')
|
||
|
return Blizzards(rows, cols, left, right, up, down)
|
||
|
|
||
|
def shortest_path(blizz, start, end, start_time):
|
||
|
visited = set()
|
||
|
q = deque()
|
||
|
while True:
|
||
|
# When do we enter the board? We can enter at any time after the start_time
|
||
|
while not q:
|
||
|
start_time += 1 # Increment first, because it takes one timestep to enter the board
|
||
|
if is_free(blizz, start[0], start[1], start_time):
|
||
|
q.append((start[0], start[1], start_time))
|
||
|
r, c, t = q.popleft()
|
||
|
if (r, c, t) in visited:
|
||
|
continue
|
||
|
visited.add((r, c, t))
|
||
|
if (r, c) == end:
|
||
|
return t + 1
|
||
|
for dr, dc in MOVES:
|
||
|
nr, nc = r + dr, c + dc
|
||
|
if 0 <= nr < blizz.rows and 0 <= nc < blizz.cols and is_free(blizz, nr, nc, t+1):
|
||
|
q.append((nr, nc, t+1))
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
b = parse(sys.stdin.read())
|
||
|
start = (0, 0)
|
||
|
end = (b.rows-1, b.cols-1)
|
||
|
t1 = shortest_path(b, start, end, 0)
|
||
|
t2 = shortest_path(b, end, start, t1)
|
||
|
t3 = shortest_path(b, start, end, t2)
|
||
|
print(t1)
|
||
|
print(t3)
|