DEV Community

Cover image for Advent of Code 2023 - December 3rd
Rob van der Leek
Rob van der Leek

Posted on

Advent of Code 2023 - December 3rd

In this series, I'll share my progress with the 2023 version of Advent of Code.

Check the first post for a short intro to this series.

You can also follow my progress on GitHub.

December 3rd

The puzzle of day 3 was quite some work. It wasn't hard to think of a solution but I needed a lot of code. I tried to reuse as much code as possible between the first and second parts, but in the end main.py is still 68 lines long.

My pitfall for this puzzle: I needed too much code, and of course that increases the risks of nasty bugs 🐛. I made a typo somewhere and because unit-tests and type-hints are lacking that cost me 30 minutes of hair-pulling debugging.

Solution here, do not click if you want to solve the puzzle first yourself
#!/usr/bin/env python3

with open('input.txt') as infile:
    lines = [line.strip() for line in infile.readlines()]

grid = []
for line in lines:
    grid.append([c for c in line])

def get_row_numbers(row):
    result = []
    cur_index = 0
    cur_number = None
    for i, c in enumerate(row): 
        if c.isdigit():
            if cur_number is None:
                cur_index = i
                cur_number = str(c)
            else:
                cur_number += str(c)
        else:
            if cur_number:
                result.append((cur_index, int(cur_number)))
                cur_number = None
    if cur_number: 
        result.append((cur_index, int(cur_number)))
    return result

def is_symbol(grid, x, y):
    if y < 0 or y > len(grid) - 1:
        return False 
    if x < 0 or x > len(grid[y]) - 1:
        return False
    return grid[y][x] != '.' and not grid[y][x].isdigit()

def get_neighbours(x, y, number):
    num_len = len(str(number))
    return [(x - 1, y), (x + num_len, y)] + \
        [(i, y - 1) for i in range(x - 1, x + num_len + 1)] + \
        [(i, y + 1) for i in range(x - 1, x + num_len + 1)]

def are_neighbours(number_x, number_y, number, x, y):
    return (x, y) in get_neighbours(number_x, number_y, number)

numbers = []
for y, row in enumerate(grid):
    for x, number in get_row_numbers(row):
        for n in get_neighbours(x, y, number):
            if is_symbol(grid, n[0], n[1]):
                numbers.append(number)
print(sum(numbers))

ratios = []
for y, row in enumerate(grid):
    for x, c in enumerate(row):
        if c == '*':
            numbers = []
            if y > 0:
                numbers.extend([n for n_x, n in get_row_numbers(grid[y - 1])
                    if are_neighbours(n_x, y - 1, n, x, y)])
            numbers.extend([n for n_x, n in get_row_numbers(row) 
                if are_neighbours(n_x, y, n, x, y)])
            if y < len(grid) - 1:
                numbers.extend([n for n_x, n in get_row_numbers(grid[y + 1])
                    if are_neighbours(n_x, y + 1, n, x, y)])
            if len(numbers) == 2:
                ratios.append(numbers[0] * numbers[1])
print(sum(ratios))
Enter fullscreen mode Exit fullscreen mode

That's it! See you again tomorrow!

Top comments (0)