Day 3 - Advent of Code 2023

Working solutions for the day 3 puzzles.

Part One

""" day_03_01.py """

# usage: python3 day_03_01.py < input

import string
import sys


def symbol(index, text, data):
    """ is a symbol adjacent text """
    width, height = data['width'], data['height']
    ignore = ['.', '\n'] + list(string.digits)
    row, col = divmod(index, width)
    for x in range(col - 1, col + len(text) + 1):
        for y in range(-1, 2):
            if 0 <= row + y < height and 0 <= x < width:
                if data['plan'][(row + y) * width + x] not in ignore:
                    return True

    return False


schematic = {'plan': [], 'width': 0, 'height': 0}

line = None
for line in sys.stdin:
    schematic['plan'].extend(line)
    schematic['height'] += 1

schematic['width'] = len(line)

values = [char if char.isdigit() else ' ' for char in schematic['plan']]
indexes = [i for i, char in enumerate(values)
           if char.isdigit() and (i == 0 or values[i - 1].isspace())]

values = ''.join(values).split()

answer = 0
for i, value in zip(indexes, values):
    if symbol(i, value, schematic):
        answer += int(value)

print(answer)

Part Two

""" day_03_02.py """

# usage: python3 day_03_02.py < input

import sys


def symbol(index, text, data):
    """ is the * symbol adjacent text """
    width, height = data['width'], data['height']
    row, col = divmod(index, width)
    for x in range(col - 1, col + len(text) + 1):
        for y in range(-1, 2):
            if 0 <= row + y < height and 0 <= x < width:
                if data['plan'][(row + y) * width + x] == '*':
                    return (row + y) * width + x

    return -1


schematic = {'plan': [], 'width': 0, 'height': 0}

line = None
for line in sys.stdin:
    schematic['plan'].extend(line)
    schematic['height'] += 1

schematic['width'] = len(line)

values = [char if char.isdigit() else ' ' for char in schematic['plan']]
indexes = [i for i, char in enumerate(values)
           if char.isdigit() and (i == 0 or values[i - 1].isspace())]

values = ''.join(values).split()

gears = {}
for i, value in zip(indexes, values):
    if (j := symbol(i, value, schematic)) > -1:
        k = gears.get(j, [])
        k.append(int(value))
        gears[j] = k

answer = 0
for i in gears.values():
    if len(i) == 2:
        answer += i[0] * i[1]

print(answer)