From dccc6a2270ac4d6cf7952953aa0c740e7786b57c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 3 Dec 2024 10:04:55 +0200 Subject: [PATCH] day-03 part-2 --- 2024/Cargo.lock | 25 ++++++++- 2024/benchmarks.txt | 27 ++++++++-- 2024/day-01.bench.txt | 6 --- 2024/day-01/bench.txt | 4 ++ 2024/day-02/bench.txt | 4 ++ 2024/day-03/Cargo.toml | 1 + 2024/day-03/bench.txt | 4 ++ 2024/day-03/src/part2.rs | 109 ++++++++++++++++++++++++++++++++++++--- 2024/justfile | 4 +- 9 files changed, 164 insertions(+), 20 deletions(-) delete mode 100644 2024/day-01.bench.txt create mode 100644 2024/day-01/bench.txt create mode 100644 2024/day-02/bench.txt create mode 100644 2024/day-03/bench.txt diff --git a/2024/Cargo.lock b/2024/Cargo.lock index e6976cb..504ac72 100644 --- a/2024/Cargo.lock +++ b/2024/Cargo.lock @@ -154,6 +154,7 @@ dependencies = [ "regex", "rstest", "test-log", + "thiserror 2.0.3", "tracing", "tracing-subscriber", ] @@ -398,7 +399,7 @@ dependencies = [ "supports-unicode", "terminal_size", "textwrap", - "thiserror", + "thiserror 1.0.69", "unicode-width", ] @@ -743,7 +744,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] @@ -757,6 +767,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.8" diff --git a/2024/benchmarks.txt b/2024/benchmarks.txt index e5ebaa0..c09b51e 100644 --- a/2024/benchmarks.txt +++ b/2024/benchmarks.txt @@ -14,8 +14,8 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s day_01_bench fastest │ slowest │ median │ mean │ samples │ iters -├─ part1 87.73 µs │ 151.9 µs │ 89.5 µs │ 95.49 µs │ 100 │ 100 -╰─ part2 235.9 µs │ 335.2 µs │ 240.3 µs │ 246.5 µs │ 100 │ 100 +├─ part1 52.85 µs │ 149.3 µs │ 53.19 µs │ 65.21 µs │ 100 │ 100 +╰─ part2 154.8 µs │ 507.2 µs │ 157.5 µs │ 199.9 µs │ 100 │ 100 running 2 tests @@ -33,6 +33,25 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s day_02_bench fastest │ slowest │ median │ mean │ samples │ iters -├─ part1 147.8 µs │ 162.6 µs │ 149.6 µs │ 150.6 µs │ 100 │ 100 -╰─ part2 214.8 µs │ 304.3 µs │ 219.8 µs │ 224.6 µs │ 100 │ 100 +├─ part1 82.71 µs │ 142.8 µs │ 92.24 µs │ 97 µs │ 100 │ 100 +╰─ part2 128.9 µs │ 170.9 µs │ 131.4 µs │ 133.2 µs │ 100 │ 100 + + +running 2 tests +ii +test result: ok. 0 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 0.00s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + +day_03_bench fastest │ slowest │ median │ mean │ samples │ iters +├─ part1 253 µs │ 1.206 ms │ 289.4 µs │ 350.7 µs │ 100 │ 100 +╰─ part2 363.5 µs │ 1.285 ms │ 411.9 µs │ 508.2 µs │ 100 │ 100 diff --git a/2024/day-01.bench.txt b/2024/day-01.bench.txt deleted file mode 100644 index 08c98bb..0000000 --- a/2024/day-01.bench.txt +++ /dev/null @@ -1,6 +0,0 @@ -day_01_bench fastest │ slowest │ median │ mean │ samples │ iters -╰─ part1 94.58 µs │ 120 µs │ 96.14 µs │ 97.09 µs │ 100 │ 100 - -day_01_bench fastest │ slowest │ median │ mean │ samples │ iters -╰─ part2 259 µs │ 351.9 µs │ 262.6 µs │ 265.9 µs │ 100 │ 100 - diff --git a/2024/day-01/bench.txt b/2024/day-01/bench.txt new file mode 100644 index 0000000..b19cba8 --- /dev/null +++ b/2024/day-01/bench.txt @@ -0,0 +1,4 @@ +day_01_bench fastest │ slowest │ median │ mean │ samples │ iters +├─ part1 66.41 µs │ 217.5 µs │ 132.6 µs │ 110.2 µs │ 100 │ 100 +╰─ part2 156.4 µs │ 397.6 µs │ 275.3 µs │ 246.7 µs │ 100 │ 100 + diff --git a/2024/day-02/bench.txt b/2024/day-02/bench.txt new file mode 100644 index 0000000..f3d6ee6 --- /dev/null +++ b/2024/day-02/bench.txt @@ -0,0 +1,4 @@ +day_02_bench fastest │ slowest │ median │ mean │ samples │ iters +├─ part1 82.1 µs │ 318 µs │ 94.04 µs │ 137.2 µs │ 100 │ 100 +╰─ part2 129.3 µs │ 176.9 µs │ 131.4 µs │ 135.1 µs │ 100 │ 100 + diff --git a/2024/day-03/Cargo.toml b/2024/day-03/Cargo.toml index 70017cc..8a15d6d 100644 --- a/2024/day-03/Cargo.toml +++ b/2024/day-03/Cargo.toml @@ -11,6 +11,7 @@ nom.workspace = true tracing.workspace = true tracing-subscriber.workspace = true miette.workspace = true +thiserror.workspace = true regex = "1.11" [dev-dependencies] diff --git a/2024/day-03/bench.txt b/2024/day-03/bench.txt new file mode 100644 index 0000000..2d0f3d0 --- /dev/null +++ b/2024/day-03/bench.txt @@ -0,0 +1,4 @@ +day_03_bench fastest │ slowest │ median │ mean │ samples │ iters +├─ part1 246.9 µs │ 778.4 µs │ 254.9 µs │ 308.9 µs │ 100 │ 100 +╰─ part2 361.4 µs │ 1.433 ms │ 379.5 µs │ 574.4 µs │ 100 │ 100 + diff --git a/2024/day-03/src/part2.rs b/2024/day-03/src/part2.rs index cbcdee4..b041517 100644 --- a/2024/day-03/src/part2.rs +++ b/2024/day-03/src/part2.rs @@ -1,9 +1,107 @@ -use miette::Result; +use miette::{Diagnostic, Result}; +use regex::Regex; +use thiserror::Error; + +#[derive(Error, Debug, Diagnostic)] +pub enum MultiplicationError { + #[error("Failed to parse first value: {0}")] + #[diagnostic(code(calculator::parse_error::first_value))] + FirstValueParseError(String), + + #[error("Failed to parse second value: {0}")] + #[diagnostic(code(calculator::parse_error::second_value))] + SecondValueParseError(String), + + #[error("Invalid multiplication format")] + #[diagnostic(code(calculator::parse_error::format))] + InvalidFormat, +} + +#[derive(Debug)] +struct Multiplication(usize, usize); + +impl Multiplication { + fn calculate(&self) -> usize { + self.0 * self.1 + } +} + +impl TryFrom<(T, U)> for Multiplication +where + T: AsRef, + U: AsRef, +{ + type Error = MultiplicationError; + fn try_from(value: (T, U)) -> std::result::Result { + let first = + value.0.as_ref().parse().map_err(|_| { + MultiplicationError::FirstValueParseError(value.0.as_ref().to_string()) + }); + let second = + value.1.as_ref().parse().map_err(|_| { + MultiplicationError::SecondValueParseError(value.1.as_ref().to_string()) + }); + Ok(Self(first?, second?)) + } +} + +#[derive(Error, Debug, Diagnostic)] +pub enum CalculatorError { + #[error("Failed to compile regex: {0}")] + #[diagnostic(code(calculator::regex_error))] + RegexError(#[from] regex::Error), + + #[diagnostic(code(calculator::multiplication_error))] + #[error("Failed to parse multiplication: {0}")] + MultiplicationError(#[from] MultiplicationError), + + #[error("Failed to process input: {0}")] + #[diagnostic(code(calculator::process_error))] + ProcessError(String), +} + +#[derive(Debug)] +struct Calculator { + do_re: Regex, + mult_re: Regex, +} + +impl Calculator { + fn new() -> Result { + Ok(Self { + do_re: Regex::new(r"^.*?don't\(\)|do\(\)(.*?)don't\(\)|do\(\).*$")?, + mult_re: Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)")?, + }) + } + + fn extract_multiplications<'a>( + &'a self, + line: &'a str, + ) -> impl Iterator + 'a { + self.mult_re.captures_iter(line).filter_map(|caps| { + Multiplication::try_from((caps.get(1)?.as_str(), caps.get(2)?.as_str())).ok() + }) + } + + fn extract_do<'a>(&'a self, line: &'a str) -> impl Iterator + 'a { + self.do_re + .captures_iter(line) + .filter_map(|caps| caps.get(0).map(|m| m.as_str())) + } + + fn process(&self, input: &str) -> usize { + let value = input.lines().collect::(); + self.extract_do(&value) + .flat_map(|line| self.extract_multiplications(line)) + .map(|mult| mult.calculate()) + .sum() + } +} #[tracing::instrument] pub fn process(input: &str) -> Result { - todo!("day xx - part 2"); - Ok(0) + let calculator = Calculator::new()?; + Ok(calculator.process(input)) } #[cfg(test)] @@ -12,9 +110,8 @@ mod tests { #[test] fn test_process() -> Result<()> { - let input = ""; - todo!("haven't built test yet"); - let result = 0; + let input = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"; + let result = 48; assert_eq!(process(input)?, result); Ok(()) } diff --git a/2024/justfile b/2024/justfile index e3039d9..d0394b2 100644 --- a/2024/justfile +++ b/2024/justfile @@ -11,8 +11,8 @@ test day part: bench-all: cargo bench -q > benchmarks.txt -bench day part: - cargo bench --bench {{day}}-bench {{part}} >> {{day}}.bench.txt +bench day: + cargo bench --bench {{day}}-bench > {{day}}/bench.txt # create the directory for a new day's puzzle and fetch the input create day: