From 05053e892813fcf710117b744e93f1f0b0356cee Mon Sep 17 00:00:00 2001 From: Jack Kinsey Date: Tue, 3 Dec 2024 23:51:48 -0500 Subject: [PATCH] Complete day 3 --- Cargo.lock | 47 ++++++++++++++++++++++++ Cargo.toml | 1 + src/day03.rs | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 6 ++-- 4 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 src/day03.rs diff --git a/Cargo.lock b/Cargo.lock index cc11b73..8a07bf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,3 +5,50 @@ version = 3 [[package]] name = "adventofcode2024" version = "0.1.0" +dependencies = [ + "regex", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" diff --git a/Cargo.toml b/Cargo.toml index 83a1806..1339bf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] +regex = "1.11.1" diff --git a/src/day03.rs b/src/day03.rs new file mode 100644 index 0000000..e0bf43c --- /dev/null +++ b/src/day03.rs @@ -0,0 +1,100 @@ +use regex::Regex; + +fn input() -> &'static str { + include_str!("../input/day03.txt") +} + +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +enum Op { + Do, + DoNot, + Mul(u16, u16), +} + +fn parse(input: &str) -> Vec { + Regex::new( + r"(?x)( # flag x ignores whitespace + (mul)\((\d\d?\d?),(\d\d?\d?)\) + | (do|don't)\(()()\) # we need throwaway groups to keep the number of groups the same + )", + ) + .unwrap() + .captures_iter(input) + .map(|c| c.extract()) + .map(|(_, [_, ins, a, b])| match ins { + "do" => Op::Do, + "don't" => Op::DoNot, + "mul" => Op::Mul(a.parse().unwrap(), b.parse().unwrap()), + _ => panic!(), + }) + .collect() +} + +fn eval(state: bool, op: &Op) -> (bool, u32) { + match (state, op) { + (_, Op::Do) => (true, 0), + (_, Op::DoNot) => (false, 0), + (true, Op::Mul(a, b)) => (state, u32::from(*a) * u32::from(*b)), + (false, Op::Mul(_, _)) => (state, 0), + } +} + +fn exec(prog: &[Op]) -> u32 { + prog.iter() + .fold((true, 0u32), |(state, n), op| { + let (new, del) = eval(state, op); + (new, n + del) + }) + .1 +} + +pub fn part1() { + let ops = parse(input()); + let n: u32 = ops.iter().map(|o| eval(true, o).1).sum(); + println!("Day 3 Part 1: {}", n); +} + +pub fn part2() { + let ops = parse(input()); + let n: u32 = exec(&ops); + println!("Day 3 Part 2: {}", n); +} + +#[cfg(test)] +mod test { + use super::*; + + const INPUT_STR: &str = + concat!("xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"); + + const INPUT_STR2: &str = + concat!("xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"); + + #[test] + fn test_parse() { + assert_eq!( + parse(INPUT_STR), + vec![Op::Mul(2, 4), Op::Mul(5, 5), Op::Mul(11, 8), Op::Mul(8, 5),] + ) + } + + #[test] + fn test_parse2() { + assert_eq!( + parse(INPUT_STR2), + vec![ + Op::Mul(2, 4), + Op::DoNot, + Op::Mul(5, 5), + Op::Mul(11, 8), + Op::Do, + Op::Mul(8, 5), + ] + ) + } + + #[test] + fn test_exec() { + assert_eq!(exec(&parse(INPUT_STR2)), 48); + } +} diff --git a/src/main.rs b/src/main.rs index 48fa201..d6680b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ pub mod day01; pub mod day02; -// pub mod day03; +pub mod day03; // pub mod day04; // pub mod day05; // pub mod day06; @@ -26,10 +26,10 @@ pub mod day02; type Part = fn(); -const DAYS: [(Part, Part); 2] = [ +const DAYS: [(Part, Part); 3] = [ (day01::part1 as fn(), day01::part2 as fn()), (day02::part1 as fn(), day02::part2 as fn()), - // (day03::part1 as fn(), day03::part2 as fn()), + (day03::part1 as fn(), day03::part2 as fn()), // (day04::part1 as fn(), day04::part2 as fn()), // (day05::part1 as fn(), day05::part2 as fn()), // (day06::part1 as fn(), day06::part2 as fn()), -- 2.38.5