Diego A. Casas

Advent of Code 2024, Day 3

Index – Advent of Code

Part One

In this puzzle, you are given a long string that represents a computer’s memory. This memory contains substrings of the form mul(x,y), where x and y are integers of 1 to 3 digits. They denote multiplication of x and y. The memory is said to be corrupted because it also contains other random, function-like expressions and symbols.

My memory is a string of 17,895 characters. The first 100 are the following:

 (who() what())>when()why()'mul(454,153)mul(565,994)(mul(890,533)#mul(875,768)+'-^where()}when()mul(

You are required to find all the mul(x,y) expressions, compute the product x * y, and sum all of these products.

This time, reading the memory was very intuitive: ReadString. I decided to use a regular expression. Since I am not experienced with those, I used RegExr for reference and interactive testing. I defined the following regular expression for the mul(x,y) expressions with 2 capture groups for x and y denoted by the unescaped parentheses.

mul\((\d{1,3}),(\d{1,3})\)

Function StringCases uses the regular expression as a pattern, and the rule operator -> tells it to return x and y from capture groups 1 and 2. The result is a list of tuples with strings of x and y. I mapped ToExpression to convert the strings into integers. Finally, MapApply allows me to compute the product for each tuple. Note that I’m using tuple in the mathematical sense, not as in Python tuples. In Wolfram Language, this tuples were sub-lists of 2 elements each.

My code looked as follows.

memory = ReadString["input.txt"]

pattern = RegularExpression["mul\\((\\d{1,3}),(\\d{1,3})\\)"]

sumProduct[memory_] :=
	memory //
	StringCases[pattern -> {"$1", "$2"}] //
	Map[ToExpression, #, {2}]& //
	MapApply[Times] //
	Total

result = sumProduct[memory]

The sum of the products was 159,892,596.

Part Two

You are told that the memory contains conditional statements do() and don't(). They enable or disable subsequent mul(x,y) expressions:

Only the most recent do() or don’t() instruction applies. At the beginning of the program, mul instructions are enabled.

I struggled with Part Two because I tried to use regular expressions. The solution, after careful thinking, was easy and reused the regular expression of Part One. I split the string at the do() statements, and for each substring I take its content until the first don't() statement (split second time and map First). The resulting list contains only enabled memory parts, so I join all the elements and apply the sumProduct function from Part One.

memoryEnabled =
	memory //
	StringSplit[#, "do()"]& //
	StringSplit[#, "don't()"]& //
	Map[First] //
	StringJoin

resultEnabled = sumProduct[memoryEnabled]

Taking into account enabled and disabled memory, the result was 92,626,942.