From 3deee94f8aee936c5826ec54d24e78797bd40638 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Fri, 5 Dec 2025 19:49:35 +0200 Subject: [PATCH] Finish day-05 part-1 --- 2025/Cargo.lock | 15 +++++ 2025/Cargo.toml | 1 + 2025/day-05/Cargo.toml | 27 ++++++++ 2025/day-05/benches/benchmarks.rs | 21 ++++++ 2025/day-05/src/bin/part1.rs | 12 ++++ 2025/day-05/src/bin/part2.rs | 12 ++++ 2025/day-05/src/lib.rs | 2 + 2025/day-05/src/part1.rs | 106 ++++++++++++++++++++++++++++++ 2025/day-05/src/part2.rs | 23 +++++++ 9 files changed, 219 insertions(+) create mode 100644 2025/day-05/Cargo.toml create mode 100644 2025/day-05/benches/benchmarks.rs create mode 100644 2025/day-05/src/bin/part1.rs create mode 100644 2025/day-05/src/bin/part2.rs create mode 100644 2025/day-05/src/lib.rs create mode 100644 2025/day-05/src/part1.rs create mode 100644 2025/day-05/src/part2.rs diff --git a/2025/Cargo.lock b/2025/Cargo.lock index 34108ce..5932691 100644 --- a/2025/Cargo.lock +++ b/2025/Cargo.lock @@ -160,6 +160,21 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "day-05" +version = "0.1.0" +dependencies = [ + "divan", + "itertools", + "miette", + "nom", + "rstest", + "test-log", + "thiserror", + "tracing", + "tracing-subscriber", +] + [[package]] name = "divan" version = "0.1.21" diff --git a/2025/Cargo.toml b/2025/Cargo.toml index 0db43d2..a146cb3 100644 --- a/2025/Cargo.toml +++ b/2025/Cargo.toml @@ -5,6 +5,7 @@ members = [ "day-02", "day-03", "day-04", + "day-05", ] default-members = ["day-*"] resolver = "2" diff --git a/2025/day-05/Cargo.toml b/2025/day-05/Cargo.toml new file mode 100644 index 0000000..c5d2b29 --- /dev/null +++ b/2025/day-05/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "day-05" +version = "0.1.0" +edition = "2024" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +itertools.workspace = true +nom.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +miette.workspace = true +thiserror.workspace = true + +[dev-dependencies] +divan.workspace = true +rstest.workspace = true +test-log.workspace = true + +[[bench]] +name = "day-05-bench" +path = "benches/benchmarks.rs" +harness = false + +[lints] +workspace = true diff --git a/2025/day-05/benches/benchmarks.rs b/2025/day-05/benches/benchmarks.rs new file mode 100644 index 0000000..02cdd0e --- /dev/null +++ b/2025/day-05/benches/benchmarks.rs @@ -0,0 +1,21 @@ +use day_05::*; + +fn main() { + divan::main(); +} + +#[divan::bench] +fn part1() { + part1::process(divan::black_box(include_str!( + "../input1.txt", + ))) + .unwrap(); +} + +#[divan::bench] +fn part2() { + part2::process(divan::black_box(include_str!( + "../input2.txt", + ))) + .unwrap(); +} diff --git a/2025/day-05/src/bin/part1.rs b/2025/day-05/src/bin/part1.rs new file mode 100644 index 0000000..27509a8 --- /dev/null +++ b/2025/day-05/src/bin/part1.rs @@ -0,0 +1,12 @@ +use day_05::part1::process; +use miette::{Context, Result}; + +#[tracing::instrument] +fn main() -> Result<()> { + tracing_subscriber::fmt::init(); + + let file = include_str!("../../input1.txt"); + let result = process(file).context("process part 1")?; + println!("{result}"); + Ok(()) +} diff --git a/2025/day-05/src/bin/part2.rs b/2025/day-05/src/bin/part2.rs new file mode 100644 index 0000000..b807b82 --- /dev/null +++ b/2025/day-05/src/bin/part2.rs @@ -0,0 +1,12 @@ +use day_05::part2::process; +use miette::{Context, Result}; + +#[tracing::instrument] +fn main() -> Result<()> { + tracing_subscriber::fmt::init(); + + let file = include_str!("../../input2.txt"); + let result = process(file).context("process part 2")?; + println!("{result}"); + Ok(()) +} diff --git a/2025/day-05/src/lib.rs b/2025/day-05/src/lib.rs new file mode 100644 index 0000000..faaf542 --- /dev/null +++ b/2025/day-05/src/lib.rs @@ -0,0 +1,2 @@ +pub mod part1; +pub mod part2; diff --git a/2025/day-05/src/part1.rs b/2025/day-05/src/part1.rs new file mode 100644 index 0000000..cd26888 --- /dev/null +++ b/2025/day-05/src/part1.rs @@ -0,0 +1,106 @@ +use std::str::FromStr; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct Id(usize); + +impl From for Id { + fn from(value: usize) -> Self { + Self(value) + } +} + +impl FromStr for Id { + type Err = String; + fn from_str(s: &str) -> Result { + let num = s.trim().parse::().map_err(|e| e.to_string())?; + Ok(Self(num)) + } +} + +#[derive(Debug, Clone, Copy)] +struct Range { + start: Id, + end: Id, +} + +impl Range { + fn contains(&self, x: Id) -> bool { + x >= self.start && x <= self.end + } +} + +impl FromStr for Range { + type Err = String; + fn from_str(s: &str) -> Result { + let (start_str, end_str) = s.trim().split_once('-').ok_or("`-` not found")?; + let start = start_str.parse::()?; + let end = end_str.parse::()?; + Ok(Self { start, end }) + } +} + +#[derive(Debug, Clone)] +struct DB { + ranges: Vec, + ids: Vec, +} + +impl DB { + fn contains(&self, x: Id) -> bool { + self.ranges.iter().any(|range| range.contains(x)) + } + + fn count_fresh(&self) -> usize { + self.ids.iter().filter(|&&id| self.contains(id)).count() + } +} + +impl FromStr for DB { + type Err = String; + fn from_str(s: &str) -> Result { + let (ranges_section, ids_section) = s + .split_once("\n\n") + .ok_or("No blank line separator found")?; + let ranges = ranges_section + .lines() + .map(Range::from_str) + .collect::, _>>()?; + let ids = ids_section + .lines() + .map(Id::from_str) + .collect::, _>>()?; + Ok(Self { ranges, ids }) + } +} + +#[tracing::instrument] +#[allow(clippy::missing_panics_doc)] +#[allow(clippy::missing_errors_doc)] +pub fn process(input: &str) -> miette::Result { + let db = DB::from_str(input).unwrap(); + Ok(db.count_fresh()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_process() -> miette::Result<()> { + let input = "3-5 +10-14 +16-20 +12-18 + +1 +5 +8 +11 +17 +32 +"; + let result = 3; + assert_eq!(process(input)?, result); + Ok(()) + } +} diff --git a/2025/day-05/src/part2.rs b/2025/day-05/src/part2.rs new file mode 100644 index 0000000..ede34a7 --- /dev/null +++ b/2025/day-05/src/part2.rs @@ -0,0 +1,23 @@ +use miette::Result; + +#[tracing::instrument] +#[allow(clippy::missing_panics_doc)] +#[allow(clippy::missing_errors_doc)] +pub fn process(input: &str) -> Result { + todo!("day xx - part 2"); + Ok(0) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_process() -> Result<()> { + let input = ""; + todo!("haven't built test yet"); + let result = 0; + assert_eq!(process(input)?, result); + Ok(()) + } +}