solved day 9 and deduplicated some code

Dieser Commit ist enthalten in:
Sebastian Tobie 2024-12-09 10:57:41 +01:00
Ursprung 9d807bbc75
Commit 1ff9286276
3 geänderte Dateien mit 169 neuen und 26 gelöschten Zeilen

1
examples/2024/09.txt Normale Datei
Datei anzeigen

@ -0,0 +1 @@
2333133121414131402

149
src/bin/2024/09.rs Normale Datei
Datei anzeigen

@ -0,0 +1,149 @@
use advent_of_code::strings::char_to_num;
#[allow(unused_imports)]
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 09);
type Disk = Vec<Option<u64>>;
fn print_disk(disk: Disk, columns: bool) {
if columns {
for i in 1..=disk.len() {
print!("{:02}", i);
}
println!()
}
for block in disk {
match block {
None => print!(" "),
Some(x) => print!("{} ", x),
}
}
println!(";")
}
fn layout_to_disk(layout: Vec<u64>) -> Disk {
let mut disk = Vec::new();
let mut space = false;
let mut block;
let mut blockid = 0;
for blocksize in layout {
block = if space {
None
} else {
blockid += 1;
Some(blockid - 1)
};
for _ in 0..blocksize {
disk.push(block);
}
space = !space;
}
disk
}
fn calculate_checksum(disk: Disk) -> u64 {
let iter = disk.iter();
let mut checksum = 0;
let mut position = 0;
for block in iter {
if block.is_some() {
checksum += block.unwrap() * position;
}
position += 1;
}
checksum
}
fn compact_blocks(disk: &mut Disk) {
let mut lastblock = disk.len() - 1;
let mut block = 0;
loop {
if disk[block].is_none() {
if disk[lastblock].is_some() {
disk[block] = disk[lastblock];
disk[lastblock] = None;
block += 1;
}
lastblock -= 1;
} else {
block += 1
}
if lastblock <= block {
break;
}
}
}
fn move_blocks(disk: &mut Disk, file_start: usize, length: usize, new_start: usize) {
for i in 0..=length {
disk[new_start + i] = disk[file_start - length + i];
disk[file_start - length + i] = None;
}
}
fn compact_files(disk: &mut Disk) {
let mut length;
let mut fileid;
let mut spaceblock;
let mut block;
let mut endblock = disk.len();
//print_disk(disk.clone(), true);
loop {
endblock -= 1;
if endblock == 0 {
break;
}
if disk[endblock].is_some() {
fileid = disk[endblock];
length = 0;
while disk[endblock - length] == fileid {
if endblock - length - 1 == 0 {
break;
}
length += 1;
}
if length == 0 {
break;
}
length -= 1;
block = 0;
loop {
if block + length >= disk.len() || block + length >= endblock {
endblock -= length;
break;
}
spaceblock = disk.get(block..=block + length).unwrap();
if spaceblock.iter().all(Option::is_none) {
move_blocks(disk, endblock, length, block);
break;
}
block += 1;
}
}
//print_disk(disk.clone(), false);
}
}
fn main() {
let mut layout = Vec::with_capacity(DATA.len());
for char in DATA.chars() {
layout.push(char_to_num(char));
}
let raw_disk = layout_to_disk(layout);
println!("Layout parsed");
let mut block_disk = raw_disk.clone();
let mut file_disk = raw_disk.clone();
compact_blocks(&mut block_disk);
let mut cksum = calculate_checksum(block_disk);
println!(
"Checksum for the blockcompacted disk is: {}",
cksum
);
compact_files(&mut file_disk);
cksum = calculate_checksum(file_disk);
println!(
"Checksum for the filecompacted disk is: {}",
cksum,
);
}

Datei anzeigen

@ -1,6 +1,23 @@
use num::{pow::Pow, Integer}; use num::{pow::Pow, Integer};
use std::ops::AddAssign; use std::ops::AddAssign;
#[inline]
pub fn char_to_num<T: Integer + From<u32>>(c: char) -> T {
match c {
'1' => T::from(1),
'2' => T::from(2),
'3' => T::from(3),
'4' => T::from(4),
'5' => T::from(5),
'6' => T::from(6),
'7' => T::from(7),
'8' => T::from(8),
'9' => T::from(9),
'0' => T::from(0),
_ => unreachable!(),
}
}
pub fn parsenumber<T: Integer + From<u32> + Pow<u32, Output = T> + AddAssign + Copy>( pub fn parsenumber<T: Integer + From<u32> + Pow<u32, Output = T> + AddAssign + Copy>(
input: &str, input: &str,
) -> T { ) -> T {
@ -9,19 +26,7 @@ pub fn parsenumber<T: Integer + From<u32> + Pow<u32, Output = T> + AddAssign + C
let mut output: T = T::from(0); let mut output: T = T::from(0);
let mut mul: u32 = 0; let mut mul: u32 = 0;
for c in input.chars().rev() { for c in input.chars().rev() {
let i: T = match c { let i: T = char_to_num(c);
'1' => T::from(1),
'2' => T::from(2),
'3' => T::from(3),
'4' => T::from(4),
'5' => T::from(5),
'6' => T::from(6),
'7' => T::from(7),
'8' => T::from(8),
'9' => T::from(9),
'0' => T::from(0),
_ => unreachable!(),
};
if mul > MAX_POWER { if mul > MAX_POWER {
return output; return output;
} }
@ -34,19 +39,7 @@ pub fn parsenumber<T: Integer + From<u32> + Pow<u32, Output = T> + AddAssign + C
pub fn get_numbers<T: Integer + From<u32>>(input: &str) -> Vec<T> { pub fn get_numbers<T: Integer + From<u32>>(input: &str) -> Vec<T> {
let mut numbers = Vec::new(); let mut numbers = Vec::new();
for char in input.chars() { for char in input.chars() {
match char { numbers.push(char_to_num(char));
'1' => numbers.push(T::from(1)),
'2' => numbers.push(T::from(2)),
'3' => numbers.push(T::from(3)),
'4' => numbers.push(T::from(4)),
'5' => numbers.push(T::from(5)),
'6' => numbers.push(T::from(6)),
'7' => numbers.push(T::from(7)),
'8' => numbers.push(T::from(8)),
'9' => numbers.push(T::from(9)),
'0' => numbers.push(T::from(0)),
_ => unimplemented!(),
}
} }
numbers numbers
} }