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)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up