-
Notifications
You must be signed in to change notification settings - Fork 0
/
15.py
93 lines (89 loc) · 2.83 KB
/
15.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
G,moves = open(0).read().split('\n\n')
G = [list(_.strip()) for _ in G.splitlines()]
#for g in G:print(' '.join(g), '/init')
moves = ''.join(moves.splitlines())
R,C=len(G),len(G[0])
D={'<': (0,-1), '>':(0,1), '^':(-1,0), 'v':(1,0)}
def printer_row(g, curriter, msg):
print(''.join(g), curriter, msg)
def printer(G, curriter, msg):
for g in G: print(''.join(g), curriter, msg)
print()
def solve(G, PART2=False):
if PART2:
for i in range(R): # transform grid
row = []
for c in G[i]:
if c == '@': row += ['@', '.']
if c == 'O': row += ['[', ']']
if c == '#': row += ['#', '#']
if c == '.': row += ['.', '.']
G[i] = row;
r,c=None,None
for i,g in enumerate(G):
for j in range(len(g)):
if g[j] == '@':
r,c = i,j
break
assert(r and c)
#for g in G: printer_row(g, None, '/init') # DBG
for i,ar in enumerate(moves):
dr,dc = D[ar]
rr,cc = r,c
stuck = False
Q = [(r,c)]
if PART2:
dq = [(r,c)]
while dq:
rr,cc = dq.pop(0)
rr,cc = rr + dr, cc + dc
if (rr,cc) in Q:
continue
thing = G[rr][cc]
if thing in '[]':
Q.append((rr,cc))
dq.append((rr,cc))
if thing == '[':
Q.append((rr,cc + 1))
dq.append((rr,cc + 1))
if thing == ']':
Q.append((rr,cc - 1))
dq.append((rr,cc - 1))
elif thing == '#':
stuck = True
break
if stuck:
continue
else:
while 42:
rr,cc = rr + dr, cc + dc
thing = G[rr][cc]
if thing == '.': break
if thing == 'O': Q.append((rr,cc))
if thing == '#':
stuck = True
break
if stuck:
continue
while Q:
br,bc = Q.pop()
if PART2:
G[br + dr][bc + dc] = G[br][bc]
else:
G[br + dr][bc + dc] = 'O'
G[br][bc] = '.'
G[r + dr][c + dc] = '@' # move myself
G[r][c] = '.' # left null
r, c = r + dr, c + dc
#printer(G, i, 'iter/evol') # DBG
res = 0
for r,g in enumerate(G):
for c,thing in enumerate(g):
if thing in ['[', 'O']:
res += 100 * r + c
printer_row(''.join(g), r, 'line/final') # DBG
return res
p1 = solve([_[:] for _ in G])
p2 = solve(G, True)
print('part 1:', p1)
print('part 2:', p2);assert(p1 in [10092, 1527563] and p2 in [9021, 1521635])