-
Notifications
You must be signed in to change notification settings - Fork 0
/
18.py
64 lines (56 loc) · 1.45 KB
/
18.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
import re#, sys
N = 71
END = 1023
g = [['.'for _ in range( N )]for _ in range( N )]
D = [(0,1),(1,0),(0,-1),(-1,0)]
lines = open(0).read().strip().splitlines()
def printer(g,path):
for r,c in path: g[r][c] = 'o'
for gg in g:print(' '.join(gg))
print()
def BFS(g):
res = None
Q = [(0,0,0,[(0,0)])]
SEEN = set()
ok = False
while Q:
node = Q.pop(0)
r,c,cost,path = node
if r == N - 1 and c == N - 1:
res = node
break
if (r,c) in SEEN: continue
SEEN.add((r,c))
for dr, dc in D:
rr,cc = r+dr,c+dc
if -1<rr<N and -1<cc<N and g[rr][cc] != '#':
Q.append((rr,cc,cost + 1,path + [(rr,cc)]))
if not res: printer(g, path) # DBG/p2
#printer(g, res[-1]) # DBG/p1
return res
def checker(n,g):
res = None
for i,line in enumerate(lines):
C,R = list(map(int,re.findall(r'\d+', line)))
assert -1<C<N and -1<R<N
g[R][C] = '#'
if i == n:
res = BFS(g)
break
return res
def p2() -> str:
l,r = 0,len(lines)
while l <= r:
mid = (l + r) // 2
res = checker(mid,[_[:] for _ in g])
if res == None:
r = mid - 1
else:
l = mid + 1
return (l,lines[l])
part1 = checker(END,[_[:] for _ in g])[2]
part2 = p2()
print('part 1:', part1)
print('part 2:', part2[1])
assert part1 in [294,22]
assert part2[1] in ['31,22','6,1']