Metadata
-
Date
-
Tagged
-
Part of series
- Advent of Code 2024 Day 1
- Advent of Code 2024 Day 2
- Advent of Code 2024 Day 3
- Advent of Code 2024 Day 4
- Advent of Code 2024 Day 5
- Advent of Code 2024 Day 6
- Advent of Code 2024 Day 7
- Advent of Code 2024 Day 8
- Advent of Code 2024 Day 9
- Advent of Code 2024 Day 10
- Advent of Code 2024 Day 11
- Advent of Code 2024 Day 12
- Advent of Code 2024 Day 13
- Advent of Code 2024 Day 14
- Advent of Code 2024 Day 15
- Advent of Code 2024 Day 16
- Advent of Code 2024 Day 17
- Advent of Code 2024 Day 18
- Advent of Code 2024 Day 19
- Advent of Code 2024 Day 20
- Advent of Code 2024 Day 21
- Advent of Code 2024 Day 22
- Advent of Code 2024 Day 23
- Advent of Code 2024 Day 24
- Advent of Code 2024 Day 25
-
Older post
-
Newer post
Advent of Code 2024 Day 3
Day 3: Mull It Over
https://adventofcode.com/2024/day/3
Today’s location to search for the chief historian is familiar (Again! Makes sense, you’ve been to many interesting places.). You remember visiting it.
The elves in charge of the place ask you to help with their computer. Something is wrong with the computer’s memory.
Ah, this feels like christmas! Going to places you haven’t been in a while and people asking you to fix their computer. Next thing you know, you’ll be reinstalling the elves’ printer drivers.
That’s your input, the memory.
An example input looks like this:
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
The goal of the program is multiplying some numbers.
It does that with instructions like mul(X,Y)
, where X
and Y
are each 1-3 digit numbers.
It then multiplies X
by Y
.
Because the memory has been corrupted, there are many invalid characters that should be ignored.
Only valid mul(X,Y)
instructions should be considered.
Part 1
If you know me, you might know I have a strong irrational hatred of regular expressions.
But even I have to admit, they’ll do well today.

To generate #1 albums, ‘jay —help’ recommends the -z flag.
HOWEVER
I coded 2 solutions again, one using regex, and a (much faster, mind you!) custom parsing thing-a-majig (solution, the word I was looking for was solution).
The question asks for the sum of all valid multiplication instructions.
Option 1: regex
use regex::Regex;
fn part_1(input: &str) -> u32 { let regex = Regex::new(r"mul\(\d{1,3},\d{1,3}\)").unwrap(); let mut sum = 0; for x in regex.find_iter(input) { let x = x.as_str(); let (a, b) = x[4..x.len() - 1].split_once(',').unwrap(); let prod = a.parse::<u32>().unwrap() * b.parse::<u32>().unwrap(); sum += prod; } sum}
Option 2: custom logic
fn part_1(input: &str) -> u32 { let memory = input.as_bytes(); let mut idx = 0; let mut sum = 0;
while idx < memory.len() { // go to next mul instruction if !memory[idx..].starts_with(b"mul(") { idx += 1; continue; } idx += 4;
// parse num 1 let mut num_1 = 0; let start_idx = idx; while memory[idx].is_ascii_digit() { num_1 *= 10; num_1 += (memory[idx] - b'0') as u32; idx += 1; } // check if number was between 1 and 3 digits if idx == start_idx || idx > start_idx + 3 { continue; }
// skip , if memory[idx] != b',' { continue; } idx += 1;
// parse num 2 let mut num_2 = 0; let start_idx = idx; while memory[idx].is_ascii_digit() { num_2 *= 10; num_2 += (memory[idx] - b'0') as u32; idx += 1; } // check if number was between 1 and 3 digits if idx == start_idx || idx > start_idx + 3 { continue; }
// skip ) if memory[idx] != b')' { continue; } idx += 1;
// add product to sum sum += num_1 * num_2; }
sum}
Part 2
There are 2 additional instructions in the corrupted memory to pay attention to.
do()
enablesmul
instructionsdon't()
disablesmul
instructions
The most recent one of these instructions applies.
If you come across a mul
, but the previous conditional was a don't()
, ignore that mul
.
In other words, those instructions flip a boolean from true
to false
,
and you should only do mul
if that boolean is true
.
mul
instructions start as enabled. (the boolean starts as true
)
Option 1: regex
use regex::Regex;
fn part_2(input: &str) -> u32 { let regex = Regex::new(r"(mul\(\d{1,3},\d{1,3}\)|do\(\))|don't\(\)").unwrap(); let mut on = true; let mut sum = 0; for regex_match in regex.find_iter(input) { match regex_match.as_str() { "do()" => on = true, "don't()" => on = false, x => { if on { let (a, b) = x[4..x.len() - 1].split_once(',').unwrap(); let prod = a.parse::<u32>().unwrap() * b.parse::<u32>().unwrap(); sum += prod; } } } } sum}
Option 2: custom logic
fn part_2(input: &str) -> u32 { let memory = input.as_bytes(); let mut on = true; let mut idx = 0; let mut sum = 0;
while idx < memory.len() { // go to next instruction match &memory[idx..] { b if b.starts_with(b"mul(") => { idx += 4; if !on { continue; } } b if b.starts_with(b"don't()") => { on = false; idx += 7; continue; } b if b.starts_with(b"do()") => { on = true; idx += 4; continue; } _ => { idx += 1; continue; } } // parse num 1 let mut num_1 = 0; let start_idx = idx; while memory[idx].is_ascii_digit() { num_1 *= 10; num_1 += (memory[idx] - b'0') as u32; idx += 1; } // check if number was between 1 and 3 digits if idx > start_idx + 3 { continue; }
// skip , if memory[idx] != b',' { continue; } idx += 1;
// parse num 2 let mut num_2 = 0; let start_idx = idx; while memory[idx].is_ascii_digit() { num_2 *= 10; num_2 += (memory[idx] - b'0') as u32; idx += 1; } // check if number was between 1 and 3 digits if idx > start_idx + 3 { continue; }
// skip ) if memory[idx] != b')' { continue; } idx += 1;
// add product to sum sum += num_1 * num_2; }
sum}
Final code
fn solve(input: &str) -> (u32, u32) { let memory = input.as_bytes(); let mut on = true; let mut idx = 0; let mut sum_1 = 0; let mut sum_2 = 0;
while idx < memory.len() { // go to next instruction match &memory[idx..] { b if b.starts_with(b"mul(") => { idx += 4; } b if b.starts_with(b"don't()") => { on = false; idx += 7; continue; } b if b.starts_with(b"do()") => { on = true; idx += 4; continue; } _ => { idx += 1; continue; } }
// parse num 1 let mut num_1 = 0; let start_idx = idx; while memory[idx].is_ascii_digit() { num_1 *= 10; num_1 += (memory[idx] - b'0') as u32; idx += 1; } // check if number was between 1 and 3 digits if idx > start_idx + 3 { continue; }
// skip , if memory[idx] != b',' { continue; } idx += 1;
// parse num 2 let mut num_2 = 0; let start_idx = idx; while memory[idx].is_ascii_digit() { num_2 *= 10; num_2 += (memory[idx] - b'0') as u32; idx += 1; } // check if number was between 1 and 3 digits if idx > start_idx + 3 { continue; }
// skip ) if memory[idx] != b')' { continue; } idx += 1;
// add product to sum let prod = num_1 * num_2; sum_1 += prod; if on { sum_2 += prod } }
(sum_1, sum_2)}