2024: day 9: part 1 and 2: rust

This commit is contained in:
Samuel Ortion 2024-12-13 17:20:01 +01:00
parent 7901645c55
commit 2ad18dce23
Signed by: sortion
GPG Key ID: 9B02406F8C4FB765
2 changed files with 122 additions and 0 deletions

View File

@ -0,0 +1,6 @@
[package]
name = "day09"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,116 @@
fn descriptor_to_disk(descriptor: String) -> Vec<i64> {
let mut file_index: i64 = 0;
let mut disk: Vec<i64> = Vec::new();
for (i, item) in descriptor.chars().enumerate() {
let item = item.to_digit(10);
if let Some(item) = item {
// If we are on a file
if i % 2 == 0 {
for _ in 0..item {
disk.push(file_index);
}
file_index += 1;
} else {
for _ in 0..item {
disk.push(-1);
}
}
}
}
disk
}
fn fragment(disk: &Vec<i64>) -> Vec<i64> {
let mut disk = disk.clone();
let mut i: usize = 0;
let mut j: usize = disk.len() - 1;
while i < j {
// If there is an empty slot
if disk[i] == -1 {
if disk[j] == -1 {
j -= 1;
} else {
// Swap an empty slot with an occupied slot
let tmp = disk[i];
disk[i] = disk[j];
disk[j] = tmp;
}
} else {
i += 1;
}
}
disk
}
fn move_file(disk: &mut Vec<i64>, file_index: i64, file_length: usize, previous_start: usize, next_start: usize) {
for i in 0..file_length {
disk[previous_start + i] = -1;
}
for i in 0..file_length {
disk[next_start + i] = file_index;
}
}
fn contiguous_empty(disk: &Vec<i64>, start_index: usize, file_length: usize) -> bool {
for i in start_index..(start_index + file_length) {
if i > disk.len() || disk[i] != -1 {
return false;
}
}
return true;
}
fn find_position(disk: &Vec<i64>, start_index: usize, file_length: usize) -> Option<usize> {
for i in 0..start_index {
if disk[i] == -1 && contiguous_empty(disk, i, file_length) {
return Some(i);
}
}
None
}
fn defragment(disk: &Vec<i64>) -> Vec<i64> {
let mut disk = disk.clone();
let max_file_index = disk.iter().cloned().fold(0, i64::max);
let mut file_index = max_file_index;
while file_index >= 0 {
let mut start_index: usize = 0;
while disk[start_index] != file_index {
start_index += 1;
}
let mut file_length: usize = 0;
while start_index + file_length < disk.len() && disk[start_index + file_length] == file_index {
file_length += 1;
}
if let Some(next_index) = find_position(&disk, start_index, file_length) {
move_file(&mut disk, file_index, file_length, start_index, next_index);
}
file_index -= 1;
}
disk
}
fn checksum(disk: &Vec<i64>) -> i64 {
let mut sum = 0;
for (i, item) in disk.iter().enumerate() {
if *item != -1 {
sum += i as i64 * (*item);
}
}
sum
}
fn main() -> std::io::Result<()> {
let disk_descriptor: String = std::io::read_to_string(std::io::stdin())?;
let disk = descriptor_to_disk(disk_descriptor);
// Part 1.
let disk1 = fragment(&disk);
let check1 = checksum(&disk1);
println!("{}", check1);
// Part 2
let disk2 = defragment(&disk);
let check2 = checksum(&disk2);
println!("{}", check2);
Ok(())
}