Untitled

 avatar
unknown
rust
4 months ago
1.9 kB
18
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.get_sum_of_values();
    (ans, now.elapsed())
}

#[derive(Debug, Clone)]
struct Stones {
    stones: HashMap<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 = line_vals.iter().copied().counts();
        Self {
            stones,
            cache: FxHashMap::default(),
        }
    }

    fn blink(&mut self) {
        let mut new_stones = HashMap::default();
        for (val, amount) in self.stones.iter() {
            let (next_val, split_val) = if let Some(cached) = self.cache.get(val) {
                *cached
            } else {
                let result = blink(*val);
                self.cache.insert(*val, result);
                result
            };
            *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;
    }

    fn get_sum_of_values(&self) -> usize {
        self.stones.iter().map(|(_, amount)| amount).sum()
    }
}

fn blink(val: usize) -> (usize, Option<usize>) {
    if val == 0 {
        return (1, None);
    } else {
        let val_str = val.to_string();
        if val_str.len() % 2 == 0 {
            let first_half = &val_str[..val_str.len() / 2].parse().unwrap();
            let second_half = &val_str[val_str.len() / 2..].parse().unwrap();
            return (*first_half, Some(*second_half));
        } else {
            return (val * 2024, None);
        }
    }
}
Editor is loading...