#!/usr/bin/env python3 import fileinput from pprint import pprint from typing import List, Tuple, Any, Set, Generator from timeit import timeit lines = list(fileinput.input()) def neighborhood( m: List[List[int]], x: int, y: int ) -> Generator[Tuple[int, int], None, None]: h = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)) yield from ( (x_ + x, y_ + y) for x_, y_ in h if 0 <= x_ + x < len(m[0]) and 0 <= y_ + y < len(m) ) def step(field): for y in range(len(field)): for x in range(len(field[y])): field[y][x] += 1 flash_queue = [ (x, y) for y in range(len(field)) for x in range(len(field[y])) if field[y][x] > 9 ] flashed = set() while flash_queue: x, y = flash_queue.pop() if (x, y) in flashed: continue flashed.add((x, y)) for x_, y_ in neighborhood(field, x, y): field[y_][x_] += 1 if field[y_][x_] > 9 and (x_, y_) not in flashed: flash_queue.append((x_, y_)) for x, y in flashed: field[y][x] = 0 return len(flashed) def main() -> Tuple[int, int]: field = [[int(c) for c in line.strip()] for line in lines] len_ = len(field) * len(field[0]) part1 = 0 part2 = 0 for part2 in range(100): part1 += step(field) while step(field) != len_ and sum(sum(row) for row in field) != 0: part2 += 1 return part1, part2 + 2 if __name__ == "__main__": print(main()) print(f"{timeit(main, number=100) * 10:.3f} ms")