Day 11
This commit is contained in:
parent
b443e3b01c
commit
7e550fd322
1 changed files with 87 additions and 0 deletions
87
src/bin/day11.rs
Normal file
87
src/bin/day11.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use std::{collections::HashMap, time::Instant};
|
||||
|
||||
use aoc_2024::{load, print_res};
|
||||
use bstr::BString;
|
||||
|
||||
type Parsed = Vec<u64>;
|
||||
|
||||
#[inline(never)]
|
||||
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
|
||||
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(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue