diff --git a/2024/rust/src/day9.rs b/2024/rust/src/day9.rs index 511ac86..bba032a 100644 --- a/2024/rust/src/day9.rs +++ b/2024/rust/src/day9.rs @@ -6,43 +6,86 @@ fn main() { show_answers(part1(&input), part2(&input)); } -fn part1(input: &str) -> usize { - let mut blocks: Vec> = vec![]; - let mut free_blocks: usize = 0; - for (i, len) in input.trim().bytes().map(|len| len - b'0').enumerate() { - // every other iteration is "free space" - let file_id = if i % 2 == 0 { - Some((i / 2) as usize) - } else { - free_blocks += len as usize; - None - }; - for _ in 0..len { - blocks.push(file_id); +struct Disk { + blocks: Vec>, + files: Vec<(usize, u8)>, + free_blocks: usize, +} + +impl FromStr for Disk { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + let mut blocks: Vec> = vec![]; + let mut files = vec![]; + let mut free_blocks: usize = 0; + for (i, len) in s.trim().bytes().map(|len| len - b'0').enumerate() { + // every other iteration is "free space" + let file_id = if i % 2 == 0 { + Some((i / 2) as usize) + } else { + free_blocks += len as usize; + None + }; + if file_id.is_some() { + files.push((blocks.len(), len)); + } + for _ in 0..len { + blocks.push(file_id); + } } + Ok(Self { + files, + blocks, + free_blocks, + }) } - println!("{blocks:?}"); - let mut right = blocks.len() - 1; - for left in 0..(right.clone() - free_blocks + 1) { - if blocks[left].is_some() { +} + +impl Disk { + fn checksum(&self) -> usize { + self.blocks + .iter() + .enumerate() + .map(|(i, b)| i * b.unwrap_or_default()) + .sum() + } +} + +fn part1(input: &str) -> usize { + let mut disk: Disk = input.parse().unwrap(); + let mut right = disk.blocks.len() - 1; + for left in 0..(right.clone() - disk.free_blocks + 1) { + if disk.blocks[left].is_some() { continue; } - while blocks[right].is_none() { + while disk.blocks[right].is_none() { right -= 1; } - (blocks[left], blocks[right]) = (blocks[right], blocks[left]); + (disk.blocks[left], disk.blocks[right]) = (disk.blocks[right], disk.blocks[left]); } - println!("{blocks:?}"); - blocks - .iter() - .enumerate() - .map(|(i, b)| i * b.unwrap_or_default()) - .sum() + disk.checksum() } fn part2(input: &str) -> usize { - 1 + let mut disk: Disk = input.parse().unwrap(); + for (cur_i, len) in disk.files.iter().rev() { + for left in 0..*cur_i { + if disk.blocks[left..(left + (*len as usize))] + .iter() + .all(|f| f.is_none()) + { + for i in 0..*len { + let i = i as usize; + (disk.blocks[left + i], disk.blocks[cur_i + i]) = + (disk.blocks[cur_i + i], disk.blocks[left + i]) + } + break; + } + } + } + disk.checksum() } #[cfg(test)] @@ -53,6 +96,6 @@ mod tests { fn test() { let input = r#"2333133121414131402"#; assert_eq!(part1(input), 1928); - assert_eq!(part2(input), 1); + assert_eq!(part2(input), 2858); } }