from re import finditer from collections import defaultdict from math import prod with open("input.txt") as f: lines = f.read().split("\n") ### part 1 symbols = { (i,j) for i, line in enumerate(lines) for j, c in enumerate(line) if c not in "1234567890." } part_numbers = [] for i, line in enumerate(lines): for match in finditer(r"\d+", line): j1, j2 = match.span() number = int(match[0]) window = { (i+x, j+y) for x in (-1, 0, 1) for y in (-1, 0, 1) for j in range(j1, j2) } for _ in window & symbols: part_numbers.append(number) part1 = sum(part_numbers) print(part1) ### part 2 potential_gears = { (i,j) for i, line in enumerate(lines) for j, c in enumerate(line) if c == "*" } parts = defaultdict(list) for i, line in enumerate(lines): for match in finditer(r"\d+", line): j1, j2 = match.span() number = int(match[0]) window = { (i+x, j+y) for x in (-1, 0, 1) for y in (-1, 0, 1) for j in range(j1, j2) } for cell in window & potential_gears: parts[cell].append(number) gear_ratios = (prod(p) for p in parts.values() if len(p) == 2) part2 = sum(gear_ratios) print(part2)