How to solve Advent of Code 2024 - Day 3 with Python

How to solve Advent of Code 2024 - Day 3 with Python

It's the most festive time of the year - Advent of Code! The highlight of every coder's December. πŸŽ„β„οΈπŸ’»πŸŽ‰
But before we get right into the first day and my solution for this day's puzzle, here is the info on how I approach this whole event (where my code is, what editor I use, etc):

Advent of Code 2024 - Info Post
It’s the most festive time of the year - Advent of Code! The highlight of every coder’s December πŸŽ„β„οΈπŸ’»πŸŽ‰ Here’s everything about my participation, I will link to this from every days’ post. What even IS Advent of Code??!! Good question, my friend. Here is this year’s about page: https:

Day 3 Puzzle

On my blog here, I will go through the puzzle and my way of solving it. If you want, you can jump directly to the code solution here:
GitHub .py script

Here is the challenge, if you want to read the full puzzle:
Advent of Code 2024 - Day 3

We visit another location you might know from previous Advent of Code events... Oh... 🀯 Is it bad that I didn't realize the theme of this year until now? Oops... πŸ˜…

You probably already knew this, but: We are looking for the Chief Historian in all the historical locations of past adventures. πŸ›οΈ

Cool, now that I've finally caught up:

Today's location is the North Pole Toboggan Rental Shop from 2020 Day 2. In typical IT worker fashion, we get asked if we can solve their computer problems. They have some corrupted memory, and we get to enjoy the joy of using regex to solve it. πŸ™„


Part 1

Day 3 gives you a sample of the corrupted input:

# Example input
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))

We need to extract the mul(number,number) parts and ignore all the corrupted ones (like mul(number,number]).

Solution Approach:
Regex. Regular Expressions. Sadly, I don't see much sense in resisting that. It has to be done and is probably what the puzzle is aiming at.

Key Code Snippets:

My Regex pattern:

pattern = re.compile(r"mul\(\d{1,3},\d{1,3}\)")

Created on regex101.com, which has a database of references and a live debugging mode - though I absolutely support just asking an AI of choice. You should read about roughly what regular expressions are, but personally, I have rarely needed them and in the few cases I do, I just let something generate them for me. πŸ€·β€β™€οΈ

Full Solution for Part 1:

Really, after the regular expression you just extract the numbers and multiply them as instructed:

def solve_part_1(mode: str = "example"):
    file_lines = read_input_file(day=3, part=1, mode=mode)

    pattern = re.compile(r"mul\(\d{1,3},\d{1,3}\)")
    matches = []

    for line in file_lines:
        matches.extend(pattern.findall(line))

    multiplication_sum = 0
    for match in matches:
        left, right = read_two_ints_from_string(match)
        multiplication_sum += left * right

    return multiplication_sum

Part 2

Here the challenge is added that instructions like do() and don't() decide which multiplications are considered for the final result.

  • add search for do() and don't() to the regular expression
  • create a current state boolean mul_active
  • change mul_active state whenever we encounter a do() or don't() in the pattern matches
  • only multiply and add to total (as in part 1) when the mul_active state is true

Full Solution for Part 2:

def solve_part_2(mode: str = "example"):
    file_lines = read_input_file(day=3, part=2, mode=mode)

    pattern = re.compile(r"mul\(\d{1,3},\d{1,3}\)|do\(\)|don't\(\)")
    matches = []

    for line in file_lines:
        matches.extend(pattern.findall(line))

    multiplication_sum = 0
    mul_active = True
    for match in matches:
        if match == "do()":
            mul_active = True
        elif match == "don't()":
            mul_active = False
        else:
            left, right = read_two_ints_from_string(match)
            if mul_active:
                multiplication_sum += left * right

    return multiplication_sum


Conclusion

Regular expressions. Probably nice for new coders to be exposed to this concept. Personally I hate using them in code since I find them highly unreadable - like badly written code - and I forget what they were meant for immediately after creating them. πŸ˜•

Writing my own parsing felt even worse though, so here we are. πŸ™ƒ