pub fn process_part1(input: &str) -> u64 { let mut ids = Vec::new(); for (file_id, chunk) in input.trim_end().as_bytes().chunks(2).enumerate() { let byte = chunk[0]; for _ in 0..(byte - 48) { ids.push(file_id.to_string()); } if let Some(&byte) = chunk.get(1) { for _ in 0..(byte - 48) { ids.push(".".into()); } } } let mut ordered = Vec::new(); while !ids.is_empty() { let id = ids.remove(0); if id == "." { while let Some(id) = ids.pop() { if id != "." { ordered.push(id); break; } } } else { ordered.push(id); } } let mut res = 0; for (multiplier, id) in ordered.iter().enumerate() { res += multiplier * id.parse::().unwrap(); } res as u64 } pub fn process_part2(input: &str) -> u64 { let mut ids = Vec::new(); for (file_id, chunk) in input.trim_end().as_bytes().chunks(2).enumerate() { let byte = chunk[0]; ids.push((file_id.to_string(), byte - 48)); if let Some(&byte) = chunk.get(1) { ids.push((".".into(), byte - 48)); } } let mut from_idx = ids.len() - 1; loop { if from_idx == 0 { break; } let (id, size) = ids[from_idx].clone(); if id == *"." { from_idx -= 1; continue; } let to_idx = if let Some(idx) = ids.iter().position(|id| id.1 >= size && id.0 == ".") { idx } else { from_idx -= 1; continue; }; if from_idx < to_idx { from_idx -= 1; continue; } let free_space = ids[to_idx].1; match size.cmp(&free_space) { std::cmp::Ordering::Less => { let remaining_free_space = free_space - size; ids[to_idx].1 = remaining_free_space; ids[from_idx] = (".".to_string(), size); ids.insert(to_idx, (id.clone(), size)); from_idx -= 1; } std::cmp::Ordering::Equal => { ids[to_idx] = (id.clone(), size); ids[from_idx] = (".".to_string(), size); from_idx -= 1; } std::cmp::Ordering::Greater => { from_idx -= 1; } } } let mut res = 0; let mut multiplier = 0; for (id, size) in ids.into_iter() { if id == *"." { multiplier += size as usize; continue; } for _idx in 0..size as usize { res += multiplier * id.parse::().unwrap(); multiplier += 1; } } res as u64 } #[cfg(test)] mod tests { use super::*; const INPUT_1: &str = "12345"; const INPUT_2: &str = "2333133121414131402"; const INPUT_3: &str = "23331331214141314020202"; #[test] fn part1_simple() { let result = process_part1(INPUT_1); assert_eq!(result, 60); } #[test] fn part1_complex_1() { let result = process_part1(INPUT_2); assert_eq!(result, 1928); } #[test] fn part1_complex_2() { let result = process_part1(INPUT_3); assert_eq!(result, 2842); } #[test] fn part2() { let result = process_part2(INPUT_2); assert_eq!(result, 2858) } }