2024: day 9: part 1 and 2: rust
This commit is contained in:
parent
7901645c55
commit
2ad18dce23
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "day09"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
|
@ -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(())
|
||||
}
|
Loading…
Reference in New Issue