#!/usr/bin/env python # -*- encoding: utf-8; py-indent-offset: 4 -*- # Author: Sebastian Mark # CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de) # pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string import re def readinput(): with open("input", "r", encoding="utf-8") as file: lines = [line.rstrip("\n") for line in file.readlines()] return lines def find_numbers(lines: list) -> set: # create a set of [(y,x,number),(y,x,number)] numbers = set() for y, line in enumerate(lines): matches = re.finditer(r"\d+", line) for match in matches: x = match.start() numbers.add((y, x, match.group())) return numbers def check_partnumber(lines: list, starty: int, startx: int, partnumber: str) -> bool: directions = [ (-1, 0), # Up (-1, 1), # Up-right (0, 1), # Right (1, 1), # Down-right (1, 0), # Down (1, -1), # Down-left (0, -1), # Left (-1, -1), # Up-left ] width = len(lines[0]) height = len(lines) for charpos in range( startx, startx + len(partnumber) ): # for all numbers in the partnumber for dy, dx in directions: # check all directions nxty, nxtx = starty + dy, charpos + dx # new checkposition if 0 <= nxtx < width and 0 <= nxty < height: # validate borders if lines[nxty][nxtx] not in "0123456789.": return True # found symbol, this is a valid partnumber return False def main(): lines = readinput() numbers = find_numbers(lines) # part 1 count = 0 for y, x, number in numbers: if check_partnumber(lines, y, x, number): count += int(number) print("Sum of partnumbers: %d" % count) if __name__ == "__main__": main()