Day 3: Mull It Over
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
You are viewing a single thread.
View all comments 2 points
Rust
use crate::utils::read_lines;
pub fn solution1() {
let lines = read_lines("src/day3/input.txt");
let sum = lines
.map(|line| {
let mut sum = 0;
let mut command_bytes = Vec::new();
for byte in line.bytes() {
match (byte, command_bytes.as_slice()) {
(b')', [.., b'0'..=b'9']) => {
handle_mul(&mut command_bytes, &mut sum);
}
_ if matches_mul(byte, &command_bytes) => {
command_bytes.push(byte);
}
_ => {
command_bytes.clear();
}
}
}
sum
})
.sum::<usize>();
println!("Sum of multiplication results = {sum}");
}
pub fn solution2() {
let lines = read_lines("src/day3/input.txt");
let mut can_mul = true;
let sum = lines
.map(|line| {
let mut sum = 0;
let mut command_bytes = Vec::new();
for byte in line.bytes() {
match (byte, command_bytes.as_slice()) {
(b')', [.., b'0'..=b'9']) if can_mul => {
handle_mul(&mut command_bytes, &mut sum);
}
(b')', [b'd', b'o', b'(']) => {
can_mul = true;
command_bytes.clear();
}
(b')', [.., b't', b'(']) => {
can_mul = false;
command_bytes.clear();
}
_ if matches_do_or_dont(byte, &command_bytes)
|| matches_mul(byte, &command_bytes) =>
{
command_bytes.push(byte);
}
_ => {
command_bytes.clear();
}
}
}
sum
})
.sum::<usize>();
println!("Sum of enabled multiplication results = {sum}");
}
fn matches_mul(byte: u8, command_bytes: &[u8]) -> bool {
matches!(
(byte, command_bytes),
(b'm', [])
| (b'u', [.., b'm'])
| (b'l', [.., b'u'])
| (b'(', [.., b'l'])
| (b'0'..=b'9', [.., b'(' | b'0'..=b'9' | b','])
| (b',', [.., b'0'..=b'9'])
)
}
fn matches_do_or_dont(byte: u8, command_bytes: &[u8]) -> bool {
matches!(
(byte, command_bytes),
(b'd', [])
| (b'o', [.., b'd'])
| (b'n', [.., b'o'])
| (b'\'', [.., b'n'])
| (b'(', [.., b'o' | b't'])
| (b't', [.., b'\''])
)
}
fn handle_mul(command_bytes: &mut Vec<u8>, sum: &mut usize) {
let first_num_index = command_bytes
.iter()
.position(u8::is_ascii_digit)
.expect("Guarunteed to be there");
let comma_index = command_bytes
.iter()
.position(|&c| c == b',')
.expect("Guarunteed to be there.");
let num1 = bytes_to_num(&command_bytes[first_num_index..comma_index]);
let num2 = bytes_to_num(&command_bytes[comma_index + 1..]);
*sum += num1 * num2;
command_bytes.clear();
}
fn bytes_to_num(bytes: &[u8]) -> usize {
bytes
.iter()
.rev()
.enumerate()
.map(|(i, digit)| (*digit - b'0') as usize * 10usize.pow(i as u32))
.sum::<usize>()
}
Definitely not my prettiest code ever. It would probably look nicer if I used regex or some parsing library, but I took on the self-imposed challenge of not using third party libraries. Also, this is already further than I made it last year!