This commit is contained in:
Fabian Schmidt 2024-12-09 13:00:45 +01:00
parent b457e10a35
commit 03bc52e5ae
4 changed files with 151 additions and 7 deletions

File diff suppressed because one or more lines are too long

20
y2024/src/bin/d9.rs Normal file
View File

@ -0,0 +1,20 @@
use std::fs;
use y2024::days::d9;
fn main() {
part1();
part2();
}
fn part1() {
let root = env!("CARGO_MANIFEST_DIR");
let content = fs::read_to_string(format!("{root}/resources/9_input.txt")).unwrap();
println!("{}", d9::process_part1(&content));
}
fn part2() {
let root = env!("CARGO_MANIFEST_DIR");
let content = fs::read_to_string(format!("{root}/resources/9_input.txt")).unwrap();
println!("{}", d9::process_part2(&content));
}

129
y2024/src/days/d9.rs Normal file
View File

@ -0,0 +1,129 @@
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)
}
}

View File

@ -1,15 +1,9 @@
pub mod d1; pub mod d1;
pub mod d2; pub mod d2;
pub mod d3; pub mod d3;
pub mod d4; pub mod d4;
pub mod d5; pub mod d5;
pub mod d6; pub mod d6;
pub mod d7; pub mod d7;
pub mod d8; pub mod d8;
pub mod d9;