feat(day9): init

This commit is contained in:
uku 2024-12-10 01:33:53 +01:00
parent 8f513f74cc
commit e1ecbe536c
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
2 changed files with 116 additions and 0 deletions

114
src/solutions/day_09.rs Normal file
View file

@ -0,0 +1,114 @@
use itertools::Itertools;
use crate::common::{Answer, Solution};
pub struct Day09;
impl Solution for Day09 {
fn name(&self) -> &'static str {
"Disk Fragmenter"
}
fn part_a(&self, input: &str) -> Answer {
let nums = input
.chars()
.map(|c| c.to_digit(10).unwrap())
.collect::<Vec<_>>();
let mut aligned_files = nums
.iter()
.step_by(2)
.enumerate()
.flat_map(|(i, &n)| vec![i; n as usize])
.collect::<Vec<_>>();
let mut final_disk = Vec::new();
for (i, n) in nums.iter().enumerate() {
if aligned_files.is_empty() {
break;
}
let len = (*n as usize).min(aligned_files.len());
if i % 2 == 0 {
final_disk.extend(aligned_files.drain(0..len));
} else {
final_disk.extend(
aligned_files
.split_off(aligned_files.len() - len)
.iter()
.rev(),
);
};
}
final_disk
.into_iter()
.enumerate()
.map(|(i, n)| i * n)
.sum::<usize>()
.into()
}
fn part_b(&self, input: &str) -> Answer {
let mut chunks = input
.chars()
.map(|c| c.to_digit(10).unwrap())
.enumerate()
.map(|(i, n)| ((i % 2 == 0).then_some(i >> 1), n))
.collect::<Vec<_>>();
let files = chunks
.iter()
.filter_map(|(o, n)| o.map(|i| (i, *n)))
.rev()
.collect::<Vec<_>>();
for (content, size) in files {
let free_idx = chunks
.iter()
.position(|(o, len)| o.is_none() && *len >= size);
// we need to recompute this because stuff moves in the vec and the element count is not constant
let orig_idx = chunks
.iter()
.position(|chunk| chunk == &(Some(content), size))
.unwrap();
if let Some(free_idx) = free_idx {
if free_idx < orig_idx {
chunks.get_mut(orig_idx).unwrap().0 = None;
chunks.insert(free_idx, (Some(content), size));
chunks.get_mut(free_idx + 1).unwrap().1 -= size;
}
}
}
chunks
.iter()
.flat_map(|(o, n)| vec![o.unwrap_or(0); *n as usize])
.enumerate()
.map(|(i, n)| i * n)
.sum::<usize>()
.into()
}
}
#[cfg(test)]
mod test {
use super::Day09;
use crate::common::Solution;
const INPUT: &str = "2333133121414131402";
#[test]
fn part_a() {
assert_eq!(Day09.part_a(INPUT), 1928.into());
}
#[test]
fn part_b() {
assert_eq!(Day09.part_b(INPUT), 2858.into());
}
}

View file

@ -8,6 +8,7 @@ mod day_05;
mod day_06;
mod day_07;
mod day_08;
mod day_09;
pub const SOLUTIONS: &[&dyn Solution] = &[
&day_01::Day01,
@ -18,4 +19,5 @@ pub const SOLUTIONS: &[&dyn Solution] = &[
&day_06::Day06,
&day_07::Day07,
&day_08::Day08,
&day_09::Day09,
];