Untitled

 avatar
unknown
rust
4 months ago
1.9 kB
24
Indexable
fn solve(stones: &Stones, iters: usize) -> (usize, Duration) {
    let now = Instant::now();
    let mut stones = stones.clone();
    for i in 1..=iters {
        stones.blink();
    }
    let ans = stones.stones.values().sum();
    (ans, now.elapsed())
}

#[derive(Debug, Clone)]
struct Stones {
    stones: FxHashMap<usize, usize>,
    cache: FxHashMap<usize, (usize, Option<usize>)>,
}

impl Stones {
    fn from_str(line: &str) -> Self {
        let line_vals = line
            .split(' ')
            .map(|x| x.parse().unwrap())
            .collect::<Vec<usize>>();
        let stones = counts(line_vals.iter().copied());
        Self {
            stones,
            cache: FxHashMap::default(),
        }
    }

    fn blink(&mut self) {
        let mut new_stones = FxHashMap::default();
        for (&val, &amount) in &self.stones {
            let (next_val, split_val) = *self.cache.entry(val).or_insert_with(|| blink(val));
            *new_stones.entry(next_val).or_insert(0) += amount;
            if let Some(split_val) = split_val {
                *new_stones.entry(split_val).or_insert(0) += amount;
            }
        }
        self.stones = new_stones.into_iter().collect();
    }
}

fn blink(val: usize) -> (usize, Option<usize>) {
    if val == 0 {
        return (1, None);
    } else {
        let len = (val as f64).log10().floor() as usize + 1;
        if len % 2 == 0 {
            let mid = len / 2;
            let divisor = 10_usize.pow(mid as u32);
            let first_half = val / divisor;
            let second_half = val % divisor;
            return (first_half, Some(second_half));
        } else {
            return (val * 2024, None);
        }
    }
}

fn counts<I>(iter: I) -> FxHashMap<I::Item, usize>
where
    I: Iterator + Sized,
    I::Item: Eq + std::hash::Hash,
{
    let mut counts = FxHashMap::default();
    iter.for_each(|item| *counts.entry(item).or_default() += 1);
    counts
}
Editor is loading...
Leave a Comment