-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday24-Blizzard Basin.py
103 lines (95 loc) · 2.56 KB
/
day24-Blizzard Basin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import math
import sys
from collections import defaultdict
from copy import deepcopy
# print(sys.getrecursionlimit())
sys.setrecursionlimit(100000)
f = open('input')
lines = f.readlines()
lines = [_.strip() for _ in lines]
WALL = set()
SNOW = defaultdict(list)
ROAD = {}
for j, line in enumerate(lines):
for i, ch in enumerate(line):
if ch == '#':
WALL.add((i, j))
elif ch in '><^v':
SNOW[(i, j)].append(ch)
else:
ROAD[(i, j)] = ch
N = len(lines[0])
M = len(lines)
start = (1, 0)
END = (N - 2, M - 1)
def adj(i, j):
for a, b in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if N > a >= 0 and M > b >= 0:
yield a, b
LCM = N * M // math.gcd(N, M)
seen = dict()
def snowMove(prevSnow, minute):
if minute % LCM in seen:
return seen[minute % LCM]
snow = prevSnow
newSnow = defaultdict(list)
for i, j in snow:
for ch in snow[(i, j)]:
ii, jj = i, j
if ch == '>':
ii += 1
if (ii, jj) in WALL:
ii = 1
elif ch == '<':
ii -= 1
if (ii, jj) in WALL:
ii = N - 2
elif ch == '^':
jj -= 1
if (ii, jj) in WALL:
jj = M - 1
if (ii, jj) in WALL:
jj -= 1
elif ch == 'v':
jj += 1
if (ii, jj) in WALL:
jj = 0
if (ii, jj) in WALL:
jj += 1
newSnow[(ii, jj)].append(ch)
seen[minute % LCM] = newSnow
return newSnow
ret = float('inf')
visited = set()
LIMIT = 300
STATE = None
def dfs(i, j, minute, end, prevSnow):
global ret, STATE
if minute > ret or minute > LIMIT: return
if (i, j) == end:
if minute < ret:
ret = minute
STATE = deepcopy(prevSnow)
return minute
minute += 1
snow = snowMove(prevSnow, minute)
for a, b in adj(i, j):
if (a, b, minute) not in visited and (a, b) not in snow and (a, b) not in WALL:
dfs(a, b, minute, end, snow)
visited.add((a, b, minute))
if (i, j) not in snow and (i, j, minute) not in visited:
dfs(i, j, minute, end, snow)
visited.add((i, j, minute))
dfs(*start, 0, END, SNOW)
part1 = ret
print('part1', part1)
LIMIT *= 2
ret = float('inf')
visited.clear()
dfs(*END, part1, start, STATE)
part2 = ret
ret = float('inf')
visited.clear()
LIMIT *= 2
dfs(*start, part2, END, STATE)
print('part2', ret)