advent of code 2025
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}')