From d98eb73cd5c7bff3ffc66e00088fd609df44952e Mon Sep 17 00:00:00 2001 From: Matt Harden Date: Wed, 1 Oct 2025 11:14:10 -0700 Subject: [PATCH 1/2] 2023 day 11. --- 2023/11/.gitignore | 1 + 2023/11/Cargo.toml | 8 +++++++ 2023/11/data/example1 | 1 + 2023/11/data/example2 | 1 + 2023/11/data/input | 1 + 2023/11/src/data.rs | 8 +++++++ 2023/11/src/main.rs | 11 +++++++++ 2023/11/src/part1/mod.rs | 44 ++++++++++++++++++++++++++++++++++++ 2023/11/src/part2/mod.rs | 48 ++++++++++++++++++++++++++++++++++++++++ 2023/11/src/puzzle.rs | 19 ++++++++++++++++ 2023/11/src/stone.rs | 25 +++++++++++++++++++++ Cargo.lock | 20 ++++++++++++----- 12 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 2023/11/.gitignore create mode 100644 2023/11/Cargo.toml create mode 100644 2023/11/data/example1 create mode 100644 2023/11/data/example2 create mode 100644 2023/11/data/input create mode 100644 2023/11/src/data.rs create mode 100644 2023/11/src/main.rs create mode 100644 2023/11/src/part1/mod.rs create mode 100644 2023/11/src/part2/mod.rs create mode 100644 2023/11/src/puzzle.rs create mode 100644 2023/11/src/stone.rs diff --git a/2023/11/.gitignore b/2023/11/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/2023/11/.gitignore @@ -0,0 +1 @@ +/target diff --git a/2023/11/Cargo.toml b/2023/11/Cargo.toml new file mode 100644 index 0000000..4cec064 --- /dev/null +++ b/2023/11/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "y2023d11" +version = "0.1.0" +edition = "2024" + +[dependencies] +anyhow = "1.0.100" +itertools.workspace = true diff --git a/2023/11/data/example1 b/2023/11/data/example1 new file mode 100644 index 0000000..ca9fe3b --- /dev/null +++ b/2023/11/data/example1 @@ -0,0 +1 @@ +0 1 10 99 999 \ No newline at end of file diff --git a/2023/11/data/example2 b/2023/11/data/example2 new file mode 100644 index 0000000..528f9d5 --- /dev/null +++ b/2023/11/data/example2 @@ -0,0 +1 @@ +125 17 \ No newline at end of file diff --git a/2023/11/data/input b/2023/11/data/input new file mode 100644 index 0000000..d6ab1eb --- /dev/null +++ b/2023/11/data/input @@ -0,0 +1 @@ +3935565 31753 437818 7697 5 38 0 123 \ No newline at end of file diff --git a/2023/11/src/data.rs b/2023/11/src/data.rs new file mode 100644 index 0000000..0ef9295 --- /dev/null +++ b/2023/11/src/data.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +pub const EXAMPLE1: &'static str = include_str!("../data/example1"); + +#[cfg(test)] +pub const EXAMPLE2: &'static str = include_str!("../data/example2"); + +#[allow(unused)] +pub const INPUT: &'static str = include_str!("../data/input"); diff --git a/2023/11/src/main.rs b/2023/11/src/main.rs new file mode 100644 index 0000000..f30aa50 --- /dev/null +++ b/2023/11/src/main.rs @@ -0,0 +1,11 @@ +mod data; +mod part1; +mod part2; +mod puzzle; +mod stone; + +fn main() { + use data::INPUT; + println!("Part 1: {}", part1::run(INPUT)); + println!("Part 2: {}", part2::run(INPUT)); +} diff --git a/2023/11/src/part1/mod.rs b/2023/11/src/part1/mod.rs new file mode 100644 index 0000000..f5a19c0 --- /dev/null +++ b/2023/11/src/part1/mod.rs @@ -0,0 +1,44 @@ +use crate::*; +use puzzle::Puzzle; +use stone::Stone; + +type Stones = Vec; + +pub fn blink(stones: &Stones) -> Stones { + stones.into_iter().flat_map(Stone::blink).collect() +} + +pub fn run(input: &str) -> usize { + let puzzle: Puzzle = input.parse().expect("parse failed"); + let mut stones = puzzle.0; + for _ in 0..25 { + stones = blink(&stones); + } + stones.len() +} + +#[cfg(test)] +mod test { + use super::*; + use anyhow::Result; + use data::EXAMPLE1; + use data::EXAMPLE2; + + #[test] + fn test_blink() -> Result<()> { + let puzzle: Puzzle = EXAMPLE1.parse()?; + assert_eq!( + blink(&puzzle.0), + [1, 2024, 1, 0, 9, 9, 2021976] + .into_iter() + .map(Stone) + .collect::() + ); + Ok(()) + } + + #[test] + fn test1() { + assert_eq!(run(EXAMPLE2), 55312); + } +} diff --git a/2023/11/src/part2/mod.rs b/2023/11/src/part2/mod.rs new file mode 100644 index 0000000..b151d8c --- /dev/null +++ b/2023/11/src/part2/mod.rs @@ -0,0 +1,48 @@ +use crate::*; +use itertools::Itertools; +use puzzle::Puzzle; +use std::collections::HashMap; +use stone::Stone; + +type Stones = HashMap; + +fn blink(stones: &Stones) -> Stones { + stones + .iter() + .flat_map(|(&stone, &count)| stone.blink().into_iter().map(move |stone| (stone, count))) + .into_grouping_map() + .sum() +} + +pub fn run(input: &str) -> usize { + let puzzle: Puzzle = input.parse().expect("parse failed"); + let mut stones: Stones = puzzle.0.iter().map(|&stone| (stone, 1usize)).collect(); + for _ in 0..75 { + stones = blink(&stones); + } + stones.into_iter().map(|(_, count)| count).sum() +} + +#[cfg(test)] +mod test { + use super::*; + use anyhow::Result; + use data::EXAMPLE1; + + #[test] + fn test_blink() -> Result<()> { + let puzzle: Puzzle = EXAMPLE1.parse()?; + let stones: Stones = puzzle.0.iter().copied().counts(); + assert_eq!( + blink(&stones), + Stones::from([ + (Stone(1), 2), + (Stone(2024), 1), + (Stone(0), 1), + (Stone(9), 2), + (Stone(2021976), 1) + ]) + ); + Ok(()) + } +} diff --git a/2023/11/src/puzzle.rs b/2023/11/src/puzzle.rs new file mode 100644 index 0000000..3179b5e --- /dev/null +++ b/2023/11/src/puzzle.rs @@ -0,0 +1,19 @@ +use crate::*; +use anyhow::Result; +use std::str::FromStr; +use stone::Stone; + +#[derive(Debug)] +pub struct Puzzle(pub Vec); + +impl FromStr for Puzzle { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(Puzzle( + s.split(' ') + .map(|s| Ok(Stone(s.parse()?))) + .collect::>()?, + )) + } +} diff --git a/2023/11/src/stone.rs b/2023/11/src/stone.rs new file mode 100644 index 0000000..4421a6a --- /dev/null +++ b/2023/11/src/stone.rs @@ -0,0 +1,25 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Stone(pub u64); + +impl Stone { + pub fn blink(&self) -> Vec { + match self.0 { + 0 => vec![Stone(1)], + n @ (10..100) => vec![Stone(n / 10), Stone(n % 10)], + n @ (1000..10000) => vec![Stone(n / 100), Stone(n % 100)], + n @ (100000..1000000) => vec![Stone(n / 1000), Stone(n % 1000)], + n @ (10000000..100000000) => vec![Stone(n / 10000), Stone(n % 10000)], + n @ (1000000000..10000000000) => vec![Stone(n / 100000), Stone(n % 100000)], + n @ (100000000000..1000000000000) => vec![Stone(n / 1000000), Stone(n % 1000000)], + n @ (10000000000000..100000000000000) => vec![Stone(n / 10000000), Stone(n % 10000000)], + n @ (1000000000000000..10000000000000000) => { + vec![Stone(n / 100000000), Stone(n % 100000000)] + } + n @ (100000000000000000..1000000000000000000) => { + vec![Stone(n / 1000000000), Stone(n % 1000000000)] + } + n @ (10000000000000000000..) => vec![Stone(n / 10000000000), Stone(n % 10000000000)], + n => vec![Stone(n * 2024)], + } + } +} diff --git a/Cargo.lock b/Cargo.lock index d6e0bbd..4817dbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrayvec" @@ -658,18 +658,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.15" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.15" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -797,6 +797,14 @@ dependencies = [ "thiserror", ] +[[package]] +name = "y2023d11" +version = "0.1.0" +dependencies = [ + "anyhow", + "itertools", +] + [[package]] name = "y2024d01" version = "0.1.0" From b12c7b31c2bac70161c267991dec148b3d057378 Mon Sep 17 00:00:00 2001 From: Matt Harden Date: Wed, 1 Oct 2025 13:46:30 -0700 Subject: [PATCH 2/2] Rename 2023 day 11 to 2024 day 11 since I did the wrong year. --- 2023/11/Cargo.toml | 8 ---- {2023 => 2024}/11/.gitignore | 0 2024/11/Cargo.toml | 10 +--- 2024/11/data/actual/input | 1 - 2024/11/data/example/input | 1 - {2023 => 2024}/11/data/example1 | 0 {2023 => 2024}/11/data/example2 | 0 {2023 => 2024}/11/data/input | 0 2024/11/src/11.rs | 73 ------------------------------ {2023 => 2024}/11/src/data.rs | 0 {2023 => 2024}/11/src/main.rs | 0 {2023 => 2024}/11/src/part1/mod.rs | 0 {2023 => 2024}/11/src/part2/mod.rs | 0 {2023 => 2024}/11/src/puzzle.rs | 0 {2023 => 2024}/11/src/stone.rs | 0 Cargo.lock | 14 +----- 16 files changed, 4 insertions(+), 103 deletions(-) delete mode 100644 2023/11/Cargo.toml rename {2023 => 2024}/11/.gitignore (100%) delete mode 100644 2024/11/data/actual/input delete mode 100644 2024/11/data/example/input rename {2023 => 2024}/11/data/example1 (100%) rename {2023 => 2024}/11/data/example2 (100%) rename {2023 => 2024}/11/data/input (100%) delete mode 100644 2024/11/src/11.rs rename {2023 => 2024}/11/src/data.rs (100%) rename {2023 => 2024}/11/src/main.rs (100%) rename {2023 => 2024}/11/src/part1/mod.rs (100%) rename {2023 => 2024}/11/src/part2/mod.rs (100%) rename {2023 => 2024}/11/src/puzzle.rs (100%) rename {2023 => 2024}/11/src/stone.rs (100%) diff --git a/2023/11/Cargo.toml b/2023/11/Cargo.toml deleted file mode 100644 index 4cec064..0000000 --- a/2023/11/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "y2023d11" -version = "0.1.0" -edition = "2024" - -[dependencies] -anyhow = "1.0.100" -itertools.workspace = true diff --git a/2023/11/.gitignore b/2024/11/.gitignore similarity index 100% rename from 2023/11/.gitignore rename to 2024/11/.gitignore diff --git a/2024/11/Cargo.toml b/2024/11/Cargo.toml index 695633f..fec5489 100644 --- a/2024/11/Cargo.toml +++ b/2024/11/Cargo.toml @@ -3,12 +3,6 @@ name = "y2024d11" version = "0.1.0" edition = "2024" -[[bin]] -name = "y2024d11" -path = "src/11.rs" - [dependencies] -bag.workspace = true -derive_more = { workspace = true, features = ["deref"] } -parse-display.workspace = true -parse-display-with.workspace = true +anyhow = "1.0.100" +itertools.workspace = true diff --git a/2024/11/data/actual/input b/2024/11/data/actual/input deleted file mode 100644 index d6ab1eb..0000000 --- a/2024/11/data/actual/input +++ /dev/null @@ -1 +0,0 @@ -3935565 31753 437818 7697 5 38 0 123 \ No newline at end of file diff --git a/2024/11/data/example/input b/2024/11/data/example/input deleted file mode 100644 index 528f9d5..0000000 --- a/2024/11/data/example/input +++ /dev/null @@ -1 +0,0 @@ -125 17 \ No newline at end of file diff --git a/2023/11/data/example1 b/2024/11/data/example1 similarity index 100% rename from 2023/11/data/example1 rename to 2024/11/data/example1 diff --git a/2023/11/data/example2 b/2024/11/data/example2 similarity index 100% rename from 2023/11/data/example2 rename to 2024/11/data/example2 diff --git a/2023/11/data/input b/2024/11/data/input similarity index 100% rename from 2023/11/data/input rename to 2024/11/data/input diff --git a/2024/11/src/11.rs b/2024/11/src/11.rs deleted file mode 100644 index 21bb87f..0000000 --- a/2024/11/src/11.rs +++ /dev/null @@ -1,73 +0,0 @@ -use bag::Bag; -use derive_more::Deref; -use parse_display::FromStr; -use parse_display_with::formats::delimiter; - -#[derive(PartialEq, Eq, Hash, FromStr)] -struct Stone(usize); - -impl Stone { - fn blink(&self) -> impl Iterator + use<> { - let n = self.0; - if n == 0 { - return vec![Stone(1)].into_iter(); - } - let digits = n.ilog10() + 1; - if digits % 2 == 0 { - let modulus = 10usize.pow(digits / 2); - return vec![Stone(n / modulus), Stone(n % modulus)].into_iter(); - } - return vec![Stone(n * 2024)].into_iter(); - } -} - -#[derive(FromStr, Deref)] -struct Stones(#[display(with=delimiter::(" "))] Bag); - -impl Stones { - fn blink(&self) -> Self { - self.iter() - .flat_map(|(stone, &count)| stone.blink().map(move |stone| (stone, count))) - .collect() - } -} - -impl FromIterator<(Stone, usize)> for Stones { - fn from_iter>(iter: T) -> Self { - Stones(iter.into_iter().collect()) - } -} - -fn run(input: &str, n: usize) -> usize { - let mut stones: Stones = input.parse().expect("Parse error."); - for _ in 0..n { - stones = stones.blink() - } - stones.count() -} - -fn part1(input: &str) -> usize { - run(input, 25) -} - -fn part2(input: &str) -> usize { - run(input, 75) -} - -#[cfg(test)] -mod tests { - use super::part1; - - const EXAMPLE: &'static str = include_str!("../data/example/input"); - - #[test] - fn test_part1() { - assert_eq!(part1(EXAMPLE), 55312); - } -} - -fn main() { - let input = include_str!("../data/actual/input"); - println!("Part 1: {}", part1(input)); - println!("Part 2: {}", part2(input)); -} diff --git a/2023/11/src/data.rs b/2024/11/src/data.rs similarity index 100% rename from 2023/11/src/data.rs rename to 2024/11/src/data.rs diff --git a/2023/11/src/main.rs b/2024/11/src/main.rs similarity index 100% rename from 2023/11/src/main.rs rename to 2024/11/src/main.rs diff --git a/2023/11/src/part1/mod.rs b/2024/11/src/part1/mod.rs similarity index 100% rename from 2023/11/src/part1/mod.rs rename to 2024/11/src/part1/mod.rs diff --git a/2023/11/src/part2/mod.rs b/2024/11/src/part2/mod.rs similarity index 100% rename from 2023/11/src/part2/mod.rs rename to 2024/11/src/part2/mod.rs diff --git a/2023/11/src/puzzle.rs b/2024/11/src/puzzle.rs similarity index 100% rename from 2023/11/src/puzzle.rs rename to 2024/11/src/puzzle.rs diff --git a/2023/11/src/stone.rs b/2024/11/src/stone.rs similarity index 100% rename from 2023/11/src/stone.rs rename to 2024/11/src/stone.rs diff --git a/Cargo.lock b/Cargo.lock index 4817dbe..c50214a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -797,14 +797,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "y2023d11" -version = "0.1.0" -dependencies = [ - "anyhow", - "itertools", -] - [[package]] name = "y2024d01" version = "0.1.0" @@ -878,10 +870,8 @@ dependencies = [ name = "y2024d11" version = "0.1.0" dependencies = [ - "bag", - "derive_more", - "parse-display", - "parse-display-with", + "anyhow", + "itertools", ] [[package]]