-
Notifications
You must be signed in to change notification settings - Fork 0
/
day_16.py
86 lines (73 loc) · 2.99 KB
/
day_16.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
import fileinput
from collections import defaultdict
from functools import partial
from itertools import chain
from multiprocessing import Pool
def main():
grid = list(map(str.rstrip, fileinput.input()))
print(part_1(grid))
print(part_2(grid))
def part_1(grid: list[str], start=(0, 0, '>')) -> int:
beams = defaultdict(set)
heads = {start}
while heads:
y, x, direction = heads.pop()
if 0 <= y < len(grid) and 0 <= x < len(grid[0]) and direction not in beams[y, x]:
beams[y, x].add(direction)
match direction:
case '>':
match grid[y][x]:
case '/':
heads.add((y - 1, x, '^'))
case '\\':
heads.add((y + 1, x, 'v'))
case '|':
heads.add((y - 1, x, '^'))
heads.add((y + 1, x, 'v'))
case _:
heads.add((y, x + 1, '>'))
case 'v':
match grid[y][x]:
case '/':
heads.add((y, x - 1, '<'))
case '\\':
heads.add((y, x + 1, '>'))
case '-':
heads.add((y, x - 1, '<'))
heads.add((y, x + 1, '>'))
case _:
heads.add((y + 1, x, 'v'))
case '<':
match grid[y][x]:
case '/':
heads.add((y + 1, x, 'v'))
case '\\':
heads.add((y - 1, x, '^'))
case '|':
heads.add((y + 1, x, 'v'))
heads.add((y - 1, x, '^'))
case _:
heads.add((y, x - 1, '<'))
case '^':
match grid[y][x]:
case '/':
heads.add((y, x + 1, '>'))
case '\\':
heads.add((y, x - 1, '<'))
case '-':
heads.add((y, x + 1, '>'))
heads.add((y, x - 1, '<'))
case _:
heads.add((y - 1, x, '^'))
case _:
raise NotImplementedError
return len(beams)
def part_2(grid: list[str]) -> int:
with Pool() as pool:
return max(pool.map(partial(part_1, grid),
chain(((y, 0, '>') for y in range(len(grid))),
((0, x, 'v') for x in range(len(grid[0]))),
((y, len(grid[0]) - 1, '<') for y in range(len(grid))),
((len(grid) - 1, x, '^') for x in range(len(grid[0]))))))
if __name__ == '__main__':
main()