1import sys
2from typing import List, Optional, Tuple
3
4removed_rolls = 0
5file = '4.input' if len(sys.argv) <= 1 else sys.argv[1]
6grid = list(map(list, map(str.strip, open(file).readlines())))
7
8def check_occupied(y: int, x: int) -> Optional[Tuple[int, int]]:
9 try:
10 if x >= 0 and y >= 0 and grid[y][x] == "@":
11 return (y, x)
12 except IndexError: pass
13 return None
14
15def compute_adj(y: int, x: int) -> List[Optional[Tuple[int, int]]]:
16 return [
17 check_occupied(y-1, x-1), check_occupied(y-1, x), check_occupied(y-1, x+1),
18 check_occupied(y, x-1), check_occupied(y, x+1),
19 check_occupied(y+1, x-1), check_occupied(y+1, x), check_occupied(y+1, x+1)
20 ]
21
22def search_removable() -> List[Tuple[int, int]]:
23 removable = []
24 for y in range(len(grid)):
25 for x in range(len(grid[y])):
26 if grid[y][x] != "@": continue
27 adj = compute_adj(y, x)
28 if sum(map(bool, adj)) < 4:
29 removable.append((y, x))
30 return removable
31
32removable = search_removable()
33print(f'p1: {len(removable)}')
34
35while len(removable):
36 for (y, x) in removable:
37 grid[y][x] = "."
38 removed_rolls += len(removable)
39 removable = search_removable()
40
41print(f'p2: {removed_rolls}')