use std::{ collections::HashMap, fs::File, io::{BufRead, BufReader}, path::Path, }; pub fn solve(input: &Path) -> anyhow::Result<()> { println!("part one: {}", part_one(input)?); println!("part two: {}", part_two(input)?); Ok(()) } fn part_one(input: &Path) -> anyhow::Result { let mut reader = BufReader::new(File::open(input)?); let mut input_str = String::new(); let _ = reader.read_line(&mut input_str)?; let mut stones: Vec> = input_str .split_whitespace() .map(|c| -> Vec { vec![c.to_string().parse().unwrap()] }) .collect(); for _ in 0..25 { for stone in &mut stones { if stone[0] == 0 { stone[0] = 1; continue; } let stone_str = stone[0].to_string(); if stone_str.len() % 2 == 0 { let (right, left) = stone_str.split_at(stone_str.len() / 2); *stone = vec![right.parse()?, left.parse()?]; } else { stone[0] *= 2024; } } stones = stones .iter() .flatten() .map(|stone| -> Vec { vec![*stone] }) .collect(); } Ok(stones.iter().flatten().count()) } fn part_two(input: &Path) -> anyhow::Result { let mut reader = BufReader::new(File::open(input)?); let mut input_str = String::new(); let _ = reader.read_line(&mut input_str)?; let input_stones: Vec = input_str .split_whitespace() .map(|c| -> usize { c.to_string().parse().unwrap() }) .collect(); let mut stones: HashMap = HashMap::new(); for stone in input_stones { if let Some(amount) = stones.get_mut(&stone) { *amount += 1; } else { stones.insert(stone, 1); } } for _ in 0..75 { for (stone, amount) in &stones.clone() { *stones.entry(*stone).or_insert(0) -= amount; if *stone == 0 { *stones.entry(1).or_insert(0) += amount; continue; } let stone_str = stone.to_string(); if stone_str.len() % 2 == 0 { let (right, left) = stone_str.split_at(stone_str.len() / 2); let right = right.parse()?; let left = left.parse()?; *stones.entry(right).or_insert(0) += amount; *stones.entry(left).or_insert(0) += amount; } else { let new = stone * 2024; *stones.entry(new).or_insert(0) += amount; } } } Ok(stones.values().sum()) }