# pyright: strict import re from collections import defaultdict from collections.abc import Iterator from functools import reduce from operator import mul from sys import stdin num_re = re.compile("[0-9]+") inp = [line.rstrip() for line in stdin] def find_adjacent_symbols( inp: list[str], ly: int, sx: int, ex: int ) -> Iterator[tuple[int, int]]: for x in range(max(0, sx - 1), min(ex + 1, len(inp[0]))): for y in range(max(0, ly - 1), min(ly + 2, len(inp))): if y == ly and sx <= x < ex: continue if inp[y][x] != "." and not inp[y][x].isdigit(): yield x, y p1 = 0 p2_gears: defaultdict[tuple[int, int], list[int]] = defaultdict(list) for ly, l in enumerate(inp): for match in num_re.finditer(l): value = int(match.group()) sx, ex = match.span() is_part_no = False for x, y in find_adjacent_symbols(inp, ly, sx, ex): if inp[y][x] == "*": p2_gears[x, y].append(value) is_part_no = True if is_part_no: p1 += value print(p1) print(sum(reduce(mul, nums) for nums in p2_gears.values() if len(nums) == 2))