diff --git a/src/bin/day11.rs b/src/bin/day11.rs new file mode 100644 index 0000000..c10ce66 --- /dev/null +++ b/src/bin/day11.rs @@ -0,0 +1,87 @@ +use std::{collections::HashMap, time::Instant}; + +use aoc_2024::{load, print_res}; +use bstr::BString; + +type Parsed = Vec; + +#[inline(never)] +pub fn parsing(input: &BString) -> color_eyre::Result { + std::str::from_utf8(input)? + .split_whitespace() + .map(|n| n.parse().map_err(Into::into)) + .collect() +} + +struct StoneMemo { + memo: HashMap<(u64, u8), u64>, +} + +impl StoneMemo { + pub fn new() -> Self { + Self { + memo: HashMap::new(), + } + } + + pub fn calculate(&mut self, stone: u64, steps: u8) -> u64 { + if steps == 0 { + return 1; + } + + if let Some(&v) = self.memo.get(&(stone, steps)) { + return v; + } + + let result = if stone == 0 { + self.calculate(1, steps - 1) + } else if stone.ilog10() % 2 == 1 { + let digits = (stone.ilog10() + 1) / 2; + let high = stone / 10u64.pow(digits); + let low = stone % 10u64.pow(digits); + + self.calculate(high, steps - 1) + self.calculate(low, steps - 1) + } else { + self.calculate(stone * 2024, steps - 1) + }; + + self.memo.insert((stone, steps), result); + + result + } +} + +#[inline(never)] +pub fn part1(input: Parsed) { + let mut memo = StoneMemo::new(); + let result: u64 = input.iter().map(|&n| memo.calculate(n, 25)).sum(); + print_res!("Number of stones: {result}") +} + +#[inline(never)] +pub fn part2(input: Parsed) { + let mut memo = StoneMemo::new(); + let result: u64 = input.iter().map(|&n| memo.calculate(n, 75)).sum(); + print_res!("Number of stones: {result}") +} + +pub fn main() -> color_eyre::Result<()> { + let context = load()?; + + let start = Instant::now(); + let parsed = parsing(&context.input)?; + let elapsed = humantime::format_duration(start.elapsed()); + + let start = Instant::now(); + if context.part == 1 { + part1(parsed); + } else { + part2(parsed); + } + let elapsed_part = humantime::format_duration(start.elapsed()); + + println!(" Parsing: {elapsed}"); + println!(" Solving: {elapsed_part}"); + + Ok(()) +}