Advent of Code 2023 - December 3rd
Tags: advent, adventofcode, python, december
Published: 2023-12-03 12:55:31

---
title: Advent of Code 2023 - December 3rd
published: true
description: My progress with the 2023 version of Advent of Code
tags: advent, adventofcode, python, december
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36qayk14ewje7rvykeg5.jpg
series: Advent of Code 2023
# published_at: 2023-12-01 17:41 +0000
---

In this series, I'll share my progress with the 2023 version of [Advent of Code](https://adventofcode.com/2023).

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

You can also follow my progress [on GitHub](https://github.com/robvanderleek/adventofcode).

## December 3rd

[The puzzle of day 3](https://adventofcode.com/2023/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 :bug:. I made a typo somewhere and because unit-tests and type-hints are lacking that cost me 30 minutes of hair-pulling debugging.

{% spoiler Solution here, do not click if you want to solve the puzzle first yourself %}

```python
#!/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))
```

{% endspoiler %}

That's it! See you again tomorrow!