AdventOfCode/y2024/src/days/d9.rs
2024-12-09 13:20:27 +01:00

130 lines
3.4 KiB
Rust

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::<usize>().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::<usize>().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)
}
}