-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathday10.py
executable file
·67 lines (47 loc) · 1.38 KB
/
day10.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
#!/usr/bin/env python3
import sys
from collections import deque
def neighbors(grid, r, c):
target = grid[r][c] + 1
for dr, dc in ((0, 1), (0, -1), (1, 0), (-1, 0)):
rr = r + dr
cc = c + dc
if 0 <= rr < len(grid) and 0 <= cc < len(grid[0]) and grid[rr][cc] == target:
yield (rr, cc)
def dfs_count_reachable_9s(grid, r, c):
q = deque([(r, c)])
seen = set()
total = 0
while q:
rc = q.pop()
if rc in seen:
continue
seen.add(rc)
r, c = rc
total += grid[r][c] == 9
q.extend(neighbors(grid, r, c))
return total
def dfs_count_paths_to_9s(grid, r, c):
# We don't need a visited set as we can only move to neighboring cells with
# higher values, so it's impossible to visit the same cell twice on the same
# path. It is however possible to visit it twice on different paths, which
# is what we want.
q = deque([(r, c)])
total = 0
while q:
r, c = q.pop()
total += grid[r][c] == 9
q.extend(neighbors(grid, r, c))
return total
# Open the first argument as input or use stdin if no arguments were given
fin = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
grid = [list(map(int, line.strip())) for line in fin]
total1 = total2 = 0
for r, row in enumerate(grid):
for c, x in enumerate(row):
if x != 0:
continue
total1 += dfs_count_reachable_9s(grid, r, c)
total2 += dfs_count_paths_to_9s(grid, r, c)
print('Part 1:', total1)
print('Part 2:', total2)