retroactive, to derust my rust

day9 part2

+95 -14
+88 -7
src/day9.rs
··· 2 2 let diskmap = parse(input); 3 3 let mut blocks = diskmap_to_blocks(&diskmap); 4 4 compact(&mut blocks); 5 - let sum = blocks 6 - .into_iter() 7 - .flatten() 8 - .enumerate() 9 - .map(|(index, block)| index as u64 * block) 10 - .sum::<u64>(); 5 + let sum = checksum(&blocks); 11 6 sum.to_string() 12 7 } 13 8 14 9 pub fn day9_part2(input: &str) -> String { 15 - todo!() 10 + let diskmap = parse(input); 11 + let compacted_diskmap = defrag_compact(&diskmap); 12 + let blocks = compacted_diskmap_to_blocks(&compacted_diskmap); 13 + let sum = checksum(&blocks); 14 + sum.to_string() 15 + } 16 + 17 + #[derive(Copy, Clone, PartialEq, Eq, Debug)] 18 + struct File { 19 + id: u64, 20 + length: usize, 21 + free_space: usize, 22 + } 23 + 24 + fn compacted_diskmap_to_blocks(compacted_diskmap: &[File]) -> Vec<Option<u64>> { 25 + compacted_diskmap 26 + .iter() 27 + .flat_map(|file| { 28 + [ 29 + vec![Some(file.id); file.length], 30 + vec![None; file.free_space], 31 + ] 32 + }) 33 + .flatten() 34 + .collect() 35 + } 36 + 37 + fn defrag_compact(diskmap: &[usize]) -> Vec<File> { 38 + let files = diskmap_to_files(diskmap); 39 + let mut compacted_files = files.clone(); 40 + 41 + for file in files.clone().into_iter().rev() { 42 + let Some(insertable_index) = compacted_files 43 + .iter() 44 + .enumerate() 45 + .find(|(_, insertable_file)| insertable_file.free_space >= file.length) 46 + .map(|(i, _)| i) 47 + else { 48 + continue; 49 + }; 50 + 51 + let prev_free_space = compacted_files[insertable_index].free_space; 52 + compacted_files[insertable_index].free_space = 0; 53 + compacted_files.insert(insertable_index + 1, file); 54 + compacted_files[insertable_index + 1].free_space = prev_free_space - file.length; 55 + 56 + let nullable_index = compacted_files 57 + .iter() 58 + .enumerate() 59 + .rev() 60 + .find(|(_, nullable_file)| nullable_file.id == file.id) 61 + .map(|(i, _)| i) 62 + .unwrap(); 63 + compacted_files[nullable_index - 1].free_space += 64 + compacted_files[nullable_index].length + compacted_files[nullable_index].free_space; 65 + compacted_files.remove(nullable_index); 66 + } 67 + 68 + compacted_files 69 + } 70 + 71 + fn diskmap_to_files(diskmap: &[usize]) -> Vec<File> { 72 + let mut id = 0u64; 73 + let mut blocks = vec![]; 74 + 75 + for digit in diskmap { 76 + if id % 2 == 0 { 77 + blocks.push(File { 78 + id: id / 2, 79 + length: *digit, 80 + free_space: 0, 81 + }); 82 + } else { 83 + blocks.last_mut().unwrap().free_space = *digit; 84 + } 85 + id += 1 86 + } 87 + 88 + blocks 89 + } 90 + 91 + fn checksum(blocks: &[Option<u64>]) -> u64 { 92 + blocks 93 + .iter() 94 + .enumerate() 95 + .map(|(index, block)| if let Some(block) = block {index as u64 * block} else {0}) 96 + .sum::<u64>() 16 97 } 17 98 18 99 fn diskmap_to_blocks(diskmap: &[usize]) -> Vec<Option<u64>> {
+7 -7
src/lib.rs
··· 357 357 let result = day9::day9_part1(include_str!("../input/day9.txt")); 358 358 assert_eq!(result, "6448989155953"); 359 359 } 360 - // #[test] 361 - // fn day9_part2_test() { 362 - // let test_result = day9::day9_part2(include_str!("../input/day9.test.txt")); 363 - // assert_eq!(test_result, "34"); 364 - // // let result = day9::day9_part2(include_str!("../input/day9.txt")); 365 - // // assert_eq!(result, "1169"); 366 - // } 360 + #[test] 361 + fn day9_part2_test() { 362 + let test_result = day9::day9_part2(include_str!("../input/day9.test.txt")); 363 + assert_eq!(test_result, "2858"); 364 + let result = day9::day9_part2(include_str!("../input/day9.txt")); 365 + assert_eq!(result, "6476642796832"); 366 + } 367 367 368 368 #[test] 369 369 fn day8_part1_test() {