This time, I am using Python for my solution.
Setup
input = open("input.txt", "r").read()
sample = \
"""xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
"""
print(f"Part 1: {part1(input)}")
print(f"Part 2: {part2(input)}")
Very minimal setup here: I read the input file, and then run the part 1 and part 2 functions on it. I don’t need to parse the input for this day as the problem asks us to do some string processing. Also, since python doesn’t have a main function, this is at the end of the file, after all the function definitions.
Part One
The program is composed of mul
instructions, which are in the exact form of mul(X,Y)
where X and Y are numbers. As the name implies, the mul
instruction is used to multiply two numbers. We then need to find the sum of all these products. This is a textbook case for using regexes and that is what I’ve done.
def part1(input):
regex_mul = re.compile(r"mul\((\d+),(\d+)\)")
sum = 0
for tup in regex_mul.findall(input):
a, b = tup
sum += int(a)*int(b)
return sum
I used a raw string for the regex to avoid escaping backslashes.when matching the round brackets.
Explaining the regular expression:
- The
mul
part of the regex matches the literal charactersm
,u
, andl
. - The
\(
and the\)
part matches the round brackets in the pattern. - The second
(
starts a capturing group which matches everything inside the round brackets. - The
\d
matches any digit character and the+
modifier means one or more than one of. So the combined\d+
matches one or more digits. - The
,
matches the comma between two numbers. - Then we have another capturing group for the second number before matching the closing bracket.
Part Two
Now, it turns out that we missed a few conditional statements.
We need to stop processing the mul statements when we see a don’t()
statement and start processing them again when we see a do()
statement.
def part2(input):
sum = 0
nxt = input
while True:
try:
valid, nxt = nxt.split("don't()", maxsplit=1)
sum += part1(valid)
except ValueError:
sum += part1(nxt)
break
try:
skip, nxt = nxt.split("do()", maxsplit=1)
except ValueError:
break
return sum
I do this by continously splitting the string into two parts, one before the don’t statement and one after.
Then I call the part one function on the before part. Then I split on the do statement and skip the part that comes before the do()
. I continue doing this in a loop until there are no do or don’t statements remaining. That happens when the split method throws a ValueError
.