Solution to Day 3

This commit is contained in:
2025-11-01 19:29:23 +01:00
parent c727f81c1a
commit 4abb3174d4

101
src/Year_2024/Day_03.py Normal file
View File

@@ -0,0 +1,101 @@
# --- Day 3: Mull It Over ---
# "Our computers are having issues, so I have no idea if we have any Chief
# Historians in stock! You're welcome to check the warehouse, though," says the
# mildly flustered shopkeeper at the North Pole Toboggan Rental Shop. The
# Historians head out to take a look.
# The shopkeeper turns to you. "Any chance you can see why our computers are
# having issues again?"
# The computer appears to be trying to run a program, but its memory (your
# puzzle input) is corrupted. All of the instructions have been jumbled up!
# It seems like the goal of the program is just to multiply some numbers. It
# does that with instructions like mul(X,Y), where X and Y are each 1-3 digit
# numbers. For instance, mul(44,46) multiplies 44 by 46 to get a result of 2024.
# Similarly, mul(123,4) would multiply 123 by 4.
# However, because the program's memory has been corrupted, there are also many
# invalid characters that should be ignored, even if they look like part of a
# mul instruction. Sequences like mul(4*, mul(6,9!, ?(12,34), or mul ( 2 , 4 )
# do nothing.
# For example, consider the following section of corrupted memory:
# xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
# Only the four highlighted sections are real mul instructions. Adding up the
# result of each instruction produces 161 (2*4 + 5*5 + 11*8 + 8*5).
# Scan the corrupted memory for uncorrupted mul instructions. What do you get if
# you add up all of the results of the multiplications?
import re
with open("P3.txt") as f:
memory = [line for line in f.read().strip().split()]
def part_1():
total = 0
pattern = re.compile(r"mul\((\d{1,3}),(\d{1,3})\)")
for line in memory:
matches = pattern.findall(line)
for match in matches:
a, b = map(int, match)
total += a * b
print(f"The sum of all multiplication results is {total}")
# --- Part Two ---
# As you scan through the corrupted memory, you notice that some of the
# conditional statements are also still intact. If you handle some of the
# uncorrupted conditional statements in the program, you might be able to get
# an even more accurate result.
# There are two new instructions you'll need to handle:
# The do() instruction enables future mul instructions.
# The don't() instruction disables future mul instructions.
# Only the most recent do() or don't() instruction applies. At the beginning of
# the program, mul instructions are enabled.
# For example:
# xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
# This corrupted memory is similar to the example from before, but this time
# the mul(5,5) and mul(11,8) instructions are disabled because there is a
# don't() instruction before them. The other mul instructions function normally,
# including the one at the end that gets re-enabled by a do() instruction.
# This time, the sum of the results is 48 (2*4 + 8*5).
# Handle the new instructions; what do you get if you add up all of the results
# of just the enabled multiplications?
def part_2():
total = 0
pattern = re.compile(r"mul\((\d{1,3}),(\d{1,3})\)|(do\(\))|((don't\(\)))")
enabled = True
for line in memory:
tokens = re.split(r"(do\(\)|don't\(\)|mul\(\d{1,3},\d{1,3}\))", line)
for token in tokens:
if token == "do()":
enabled = True
elif token == "don't()":
enabled = False
else:
matches = pattern.findall(token)
for match in matches:
if enabled:
a, b = map(int, match[:2])
total += a * b
print(f"The sum of all enabled multiplication results is {total}")
if __name__ == "__main__":
part_1()
part_2()