diff --git a/Cargo.lock b/Cargo.lock index b51871d..fb1fc33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,6 +73,7 @@ version = "0.1.0" dependencies = [ "clap", "color-eyre", + "itertools", ] [[package]] @@ -169,6 +170,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "eyre" version = "0.6.12" @@ -203,6 +210,15 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "lazy_static" version = "1.5.0" diff --git a/Cargo.toml b/Cargo.toml index 29c228c..2491122 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] clap = { version = "4.5.53", features = ["derive"] } color-eyre = "0.6.5" +itertools = "0.14.0" diff --git a/src/solutions/day_02.rs b/src/solutions/day_02.rs index 0bb7a38..6670ef1 100644 --- a/src/solutions/day_02.rs +++ b/src/solutions/day_02.rs @@ -1,3 +1,7 @@ +use std::io::Write; + +use itertools::Itertools; + use crate::solution::Solution; #[derive(Clone, Copy, Debug)] @@ -18,17 +22,39 @@ impl IdRange { struct Id(u64); impl Id { - fn contains_repeat(&self) -> bool { - let s = self.0.to_string(); + fn contains_double_repeat(&self, buf: &mut Vec) -> bool { + buf.clear(); + write!(buf, "{}", self.0).unwrap(); - if !s.len().is_multiple_of(2) { + if !buf.len().is_multiple_of(2) { return false; } - let (left, right) = s.split_at(s.len() / 2); + let (left, right) = buf.split_at(buf.len() / 2); left == right } + + fn contains_any_repeat(&self, buf: &mut Vec) -> bool { + if self.contains_double_repeat(buf) { + return true; + } + + buf.clear(); + write!(buf, "{}", self.0).unwrap(); + + for num_parts in 2..=buf.len() { + if !buf.len().is_multiple_of(num_parts) { + continue; + } + + if buf.chunks_exact(buf.len() / num_parts).all_equal() { + return true; + } + } + + false + } } #[derive(Debug)] @@ -43,10 +69,22 @@ impl Solution for Day02 { } fn part1(&self) -> String { + let mut buf = Vec::with_capacity(10); + + self.ranges + .iter() + .flat_map(IdRange::ids) + .filter_map(|id| id.contains_double_repeat(&mut buf).then_some(id.0)) + .sum::() + .to_string() + } + + fn part2(&self) -> String { + let mut buf = Vec::with_capacity(10); self.ranges .iter() .flat_map(IdRange::ids) - .filter_map(|id| id.contains_repeat().then_some(id.0)) + .filter_map(|id| id.contains_any_repeat(&mut buf).then_some(id.0)) .sum::() .to_string() }