import re NUMBERS = "0123456789" EXAMPLE = """ 467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.. """ def clean(text: str) -> list[str]: return list(filter(lambda l: l.strip() != "", text.splitlines())) def is_adj_to_symbol(x, y, lines): non_symbol = re.compile(r"[^0-9\.]") for xo, yo in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]: try: if x + xo < 0 or y + yo < 0: continue if non_symbol.match(lines[y + yo][x + xo]): return True except IndexError: pass return False def solve(lines: list[str]): d = "" adj_to_symbol = False s = 0 for (y, line) in enumerate(lines): for (x, c) in enumerate(line): if c not in NUMBERS: if len(d) > 0 and adj_to_symbol: s += int(d) d = "" adj_to_symbol = False else: if is_adj_to_symbol(x, y, lines): adj_to_symbol = True d = d + c return s def get_entire_number(x, y, lines): assert(lines[y][x] in NUMBERS) x_start = x - 1 while lines[y][x_start] in NUMBERS and x_start >= 0: x_start -= 1 x_start += 1 x_start_orig = x_start r = "" while x_start < len(lines[0]) and lines[y][x_start] in NUMBERS: r += lines[y][x_start] x_start += 1 return x_start_orig, int(r) def find_sourrounding_numbers(x, y, lines): full_coords = [] numbers = [] for xo, yo in [(-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)]: new_x = x + xo new_y = y + yo if new_x < 0 or new_y < 0 or new_x >= len(lines[0]) or new_y >= len(lines): continue if lines[new_y][new_x] in NUMBERS: x_start_orig, n = get_entire_number(new_x, new_y, lines) if (x_start_orig, new_y, n) not in full_coords: numbers.append(n) full_coords.append((x_start_orig, y + yo, n)) return numbers def solve2(lines: list[str]): s = 0 for (y, line) in enumerate(lines): for (x, c) in enumerate(line): if c == '*': numbers = find_sourrounding_numbers(x, y, lines) if len(numbers) == 2: # print(numbers) s += numbers[0] * numbers[1] return s def main(): example = clean(EXAMPLE) print("Example 1:", solve(example)) data = clean(open("i3.txt").read()) print("Solution 1:", solve(data)) example = clean(EXAMPLE) print("Example 2:", solve2(example)) data = clean(open("i3.txt").read()) print("Solution 2:", solve2(data)) if __name__ == "__main__": main()