From 85d9d0c91008a7686f57b64ecf8b858769ae42ce Mon Sep 17 00:00:00 2001 From: Bram Date: Mon, 16 Dec 2024 16:37:05 +0000 Subject: [PATCH] Add Rust day 11 --- inputs/11.txt | 1 + src/day_11/mod.rs | 91 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 8 ++++ src/main.rs | 1 + src/utils/diagnostics.rs | 6 +-- 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 inputs/11.txt create mode 100644 src/day_11/mod.rs diff --git a/inputs/11.txt b/inputs/11.txt new file mode 100644 index 0000000..6e89785 --- /dev/null +++ b/inputs/11.txt @@ -0,0 +1 @@ +64599 31 674832 2659361 1 0 8867 321 \ No newline at end of file diff --git a/src/day_11/mod.rs b/src/day_11/mod.rs new file mode 100644 index 0000000..6cdbe31 --- /dev/null +++ b/src/day_11/mod.rs @@ -0,0 +1,91 @@ +use crate::utils; +use std::collections::HashMap; + +type Collection = HashMap; +type Count = u64; +type Stone = u64; + +pub fn answer(text : String) -> ( Count, Count ) { + let coll = stones_from_string(text); + + let c_25 = blink_at_collection_times(coll, 25); + let p1 : Count = collection_size(&c_25); + + let c_75 = blink_at_collection_times(c_25, 50); + let p2 : Count = collection_size(&c_75); + + ( p1, p2 ) +} + +fn blink_at_collection(coll : &Collection) -> Collection { + let mut newc : Collection = HashMap::new(); + + for (key, value) in coll.iter() { + let (stone1, mstone2) = blink_stone(*key); + + newc.entry(stone1) + .and_modify(|counter| *counter += *value) + .or_insert(*value); + + if let Some(stone2) = mstone2 { + newc.entry(stone2) + .and_modify(|counter| *counter += *value) + .or_insert(*value); + } + } + + newc +} + +fn blink_at_collection_times(start : Collection, n : u8) -> Collection { + let mut coll : Collection = start; + + for _ in 0..n { + coll = blink_at_collection(&coll); + } + + coll +} + +fn blink_stone(stone : Stone) -> (Stone, Option) { + if stone == 0 { + ( 1, None ) + } else if let Some(( s1, s2 )) = split_stone(&stone) { + ( s1, Some(s2) ) + } else { + ( 2024 * stone, None ) + } +} + +fn collection_size(coll : &Collection) -> Count { + coll.iter().map(|(_, v)| v).sum() +} + +fn split_stone(stone : &Stone) -> Option<(Stone, Stone)> { + let s : String = stone.to_string(); + + if s.len() % 2 == 0 { + let i = s.len() / 2; + let s1 = str_to_stone(&s[..i])?; + let s2 = str_to_stone(&s[i..])?; + Some(( s1, s2 )) + } else { + None + } +} + +fn stones_from_string(s : String) -> Collection { + let mut collection = HashMap::new(); + + for stone in s.split(" ").filter_map(str_to_stone) { + collection.entry(stone) + .and_modify(|counter| *counter = *counter + 1) + .or_insert(1); + } + + collection +} + +fn str_to_stone(s : &str) -> Option { + s.trim().to_string().parse::().ok() +} diff --git a/src/lib.rs b/src/lib.rs index c94223f..0e176e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ mod day_07; mod day_08; mod day_09; mod day_10; +mod day_11; mod utils; use std::time::Duration; @@ -78,3 +79,10 @@ pub fn day_10() -> DailyOutput { ( p1 as u128, p2 as u128, d ) } + +pub fn day_11() -> DailyOutput { + let s : String = read_from_file("inputs/11.txt"); + let (p1, p2, d) = diagnostics::benchmark(s, day_11::answer); + + ( p1 as u128, p2 as u128, d ) +} diff --git a/src/main.rs b/src/main.rs index 8c17f36..c9758a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ fn main() { aoc.insert(8, aoc_2024::day_08()); aoc.insert(9, aoc_2024::day_09()); aoc.insert(10, aoc_2024::day_10()); + aoc.insert(11, aoc_2024::day_11()); aoc.show_diagnostics(); } diff --git a/src/utils/diagnostics.rs b/src/utils/diagnostics.rs index 4e53d50..2003a79 100644 --- a/src/utils/diagnostics.rs +++ b/src/utils/diagnostics.rs @@ -29,7 +29,7 @@ impl AdventOfCode { } pub fn show_diagnostics(&self) { - println!("| | {: ^14} | {: ^14} | Duration |", + println!("| | {: ^15} | {: ^15} | Duration |", "Part 1", "Part 2" ); @@ -70,7 +70,7 @@ impl DayResults { let r = horizontal_bar('#', ' ', 4.0 * BAR_WIDTH_UNIT * (fraction - 0.75), BAR_WIDTH_UNIT); format!( - "| Day {: >2} | {: >14} | {: >14} | {: >6}ms | [{: <}{: <6}{: <6}", + "| Day {: >2} | {: >15} | {: >15} | {: >6}ms | [{: <}{: <6}{: <6}", day, self.part_1, self.part_2, self.duration.as_millis(), g.as_str().green(), o.as_str().yellow(), r.as_str().red() ) @@ -86,7 +86,7 @@ pub fn benchmark(s : String, f : fn(String) -> ( A, B )) -> ( A, B, Duratio } fn empty_diagnostic(day : usize) -> String { - format!("| Day {: >2} | {:->14} | {:->14} | {:->8} | [", day, "", "", "") + format!("| Day {: >2} | {:->15} | {:->15} | {:->8} | [", day, "", "", "") } fn horizontal_bar(full : char, empty : char, width : f32, max_width : f32) -> String {