70 lines
1.8 KiB
Python
70 lines
1.8 KiB
Python
|
#!/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()
|