use std::collections::HashMap; fn blink(stone: u64) -> Vec { let mut new_stones: Vec = Vec::new(); if stone == 0 { new_stones.push(1); } else { let stone_str = stone.to_string(); if stone_str.len() % 2 == 0 { let index: usize = stone_str.len() / 2; let part1 = &stone_str[..index]; let part2 = &stone_str[index..]; let part1: u64 = part1.parse().unwrap(); let part2: u64 = part2.parse().unwrap(); new_stones.push(part1); new_stones.push(part2); } else { new_stones.push(stone * 2024); } } new_stones } fn blink_synchronous(stones: &Vec) -> Vec { let mut new_stones: Vec = Vec::new(); for &stone in stones { let mut stone_children = blink(stone); new_stones.append(&mut stone_children); } new_stones } fn blink_memory(stone: u64, nb_blinks: usize, blinked: &mut HashMap<(u64, usize), usize>) -> usize { if nb_blinks == 0 { return 1; } else { if let Some(size) = blinked.get(&(stone, nb_blinks)) { return *size; } else { let mut sum = 0; for other_stone in blink(stone) { sum += blink_memory(other_stone, nb_blinks - 1, blinked); } blinked.insert((stone, nb_blinks), sum); return sum; } } } fn main() -> std::io::Result<()> { let stones: String = std::io::read_to_string(std::io::stdin())?; let mut stones: Vec = stones .split(" ") .map(|e| e.parse::()) .filter(|e| e.is_ok()) .map(|e| e.unwrap()).collect(); stones.push(1); println!("{:?}", stones); // Part 1. let mut current_stones: Vec = stones.clone(); for _ in 0..25 { current_stones = blink_synchronous(¤t_stones); } println!("{}", current_stones.len()); // Part 2. let mut blinked: HashMap<(u64, usize), usize> = HashMap::new(); let mut sum: usize = 0; for stone in stones { let size = blink_memory(stone, 75, &mut blinked); sum += size; } println!("{}", sum); Ok(()) }