Advent of Code solutions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Day 9

Ben C 443eb038 47a7b2ec

+149 -7
+143 -7
years/2024/src/day_9.rs
··· 1 + use advent_core::{day_stuff, ex_for_day, Day}; 1 2 2 - use advent_core::{Day, day_stuff, ex_for_day}; 3 + pub struct Day9; 4 + 5 + #[derive(Clone, Debug)] 6 + pub enum Block { 7 + File(usize), 8 + Blank, 9 + } 10 + 11 + #[derive(Debug, Clone)] 12 + pub struct Disk { 13 + data: Vec<(Block, usize)>, 14 + } 15 + 16 + impl Disk { 17 + pub fn parse(input: &str) -> Self { 18 + let data = input 19 + .chars() 20 + .enumerate() 21 + .map(|(i, c)| { 22 + let size = c.to_string().parse::<usize>().unwrap(); 23 + if i % 2 == 0 { 24 + (Block::File(i / 2), size) 25 + } else { 26 + (Block::Blank, size) 27 + } 28 + }) 29 + .collect::<Vec<_>>(); 30 + Self { data } 31 + } 32 + 33 + pub fn checksum(&self) -> usize { 34 + self.data 35 + .iter() 36 + .enumerate() 37 + .fold( 38 + (0, 0_usize), 39 + |(current_index, total), (_, (block, size))| match block { 40 + Block::Blank => (current_index + size, total), 41 + Block::File(id) => ( 42 + current_index + size, 43 + total 44 + + (current_index..current_index + size) 45 + .map(|i| *id * i) 46 + .sum::<usize>(), 47 + ), 48 + }, 49 + ) 50 + .1 51 + } 52 + 53 + #[allow(unused)] 54 + pub fn display(&self) -> String { 55 + self.data 56 + .iter() 57 + .map(|(b, s)| match b { 58 + Block::Blank => ".".repeat(*s), 59 + Block::File(id) => id.to_string().repeat(*s), 60 + }) 61 + .collect::<String>() 62 + } 3 63 4 - pub struct Day9; 64 + /// (position, size) 65 + pub fn iter_blanks_before(&self, i: usize) -> impl Iterator<Item = (usize, usize)> + use<'_> { 66 + self.data.iter().enumerate().filter_map(move |(j, b)| { 67 + if let (Block::Blank, b_amnt) = b 68 + && j < i 69 + { 70 + Some((j, *b_amnt)) 71 + } else { 72 + None 73 + } 74 + }) 75 + } 76 + 77 + /// If we inserted once 78 + /// Assumes i > j, j describes [Block::Blank], i describes [Block::File]. 79 + pub fn swap_blocks(&mut self, i: usize, j: usize) -> bool { 80 + let a = self.data[i].clone(); 81 + let b = self.data[j].clone(); 82 + 83 + if a.1 == b.1 { 84 + self.data.swap(i, j); 85 + false 86 + } else { 87 + if a.1 > b.1 { 88 + self.data[i].1 -= b.1; 89 + self.data[j].0 = a.0.clone(); 90 + self.data.insert(i + 1, (b.0.clone(), a.1 - b.1)); 91 + } else { 92 + self.data[j] = a.clone(); 93 + self.data[i].0 = b.0.clone(); 94 + self.data.insert(j + 1, (b.0.clone(), b.1 - a.1)); 95 + } 96 + 97 + true 98 + } 99 + } 100 + } 5 101 6 102 impl Day for Day9 { 103 + day_stuff!(9, "1928", "2858", Disk); 7 104 8 - day_stuff!(9, "", ""); 105 + fn part_1(mut input: Self::Input) -> Option<String> { 106 + let mut i = input.data.len() - 1; 107 + loop { 108 + if let (Block::File(_), _) = input.data[i] { 109 + let next_blank = input.iter_blanks_before(i).next(); 110 + if let Some((j, _)) = next_blank { 111 + if input.swap_blocks(i, j) { 112 + i += 1; 113 + } 114 + } 115 + } 116 + if i == 0 { 117 + break; 118 + } else { 119 + i -= 1; 120 + } 121 + } 122 + 123 + Some(input.checksum().to_string()) 124 + } 125 + 126 + fn part_2(mut input: Self::Input) -> Option<String> { 127 + let mut i = input.data.len() - 1; 128 + 129 + loop { 130 + if let (Block::File(_), size) = input.data[i] { 131 + let next_blank = input 132 + .iter_blanks_before(i) 133 + .find(|(_, b_amnt)| *b_amnt >= size); 134 + if let Some((j, _)) = next_blank { 135 + if input.swap_blocks(i, j) { 136 + i += 1; 137 + } 138 + } 139 + } 140 + if i == 0 { 141 + break; 142 + } else { 143 + i -= 1; 144 + } 145 + } 9 146 10 - fn part_1(_input: Self::Input) -> Option<String> { 11 - None 147 + Some(input.checksum().to_string()) 12 148 } 13 149 14 - fn part_2(_input: Self::Input) -> Option<String> { 15 - None 150 + fn parse_input(input: &str) -> Self::Input { 151 + Disk::parse(input.trim()) 16 152 } 17 153 }
+1
years/2024/src/examples/day_9/1.txt
··· 1 + 2333133121414131402
+1
years/2024/src/examples/day_9/2.txt
··· 1 + 2333133121414131402
+2
years/2024/src/lib.rs
··· 1 + #![feature(let_chains)] 2 + 1 3 use macros::year; 2 4 3 5 year!(2024);
+2
years/2024/src/main.rs
··· 1 + #![feature(let_chains)] 2 + 1 3 use macros::year_runner; 2 4 3 5 year_runner!(2024);