This commit is contained in:
StNicolay 2024-12-09 18:04:05 +03:00
parent cc04168468
commit ec647002cd
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
2 changed files with 140 additions and 2 deletions

137
src/day9.rs Normal file
View File

@ -0,0 +1,137 @@
use std::{
fs::File,
io::{BufReader, Read},
iter,
};
use itertools::Itertools;
#[derive(Copy, Clone)]
enum Block {
Free,
File { id: usize },
}
impl Block {
fn is_free(&self) -> bool {
matches!(self, Self::Free)
}
fn file_id(&self) -> usize {
match self {
Self::File { id } => *id,
Self::Free => unreachable!(),
}
}
}
fn get_data() -> Vec<Block> {
let mut result = vec![];
let reader = BufReader::new(File::open("input.txt").unwrap());
for (i, b) in reader.bytes().enumerate() {
let num = b.unwrap() - b'0';
let record = if i % 2 == 0 {
Block::File { id: i / 2 }
} else {
Block::Free
};
result.extend(iter::repeat(record).take(num as usize));
}
result
}
#[derive(Clone, Copy)]
struct LBlock {
start: usize,
end: usize,
}
impl LBlock {
fn len(&self) -> usize {
self.end - self.start
}
}
fn checksum(mem: &[Block]) -> usize {
mem.iter()
.enumerate()
.filter(|(_i, block)| !block.is_free())
.map(|(i, block)| i * block.file_id())
.sum()
}
pub fn task1() {
let mut data = get_data();
let mut lo = 0;
let mut ro = data.len() - 1;
while lo < ro {
while lo < data.len() && !data[lo].is_free() {
lo += 1;
}
while ro > lo && data[ro].is_free() {
ro -= 1;
}
data.swap(lo, ro);
lo += 1;
ro = ro.saturating_sub(1);
}
println!("{}", checksum(&data));
}
pub fn task2() {
let mut data = get_data();
let mut free_mem = vec![];
let mut files = vec![];
for (is_free, mut chunk) in &data
.iter()
.enumerate()
.chunk_by(|(_i, block)| block.is_free())
{
if is_free {
let (fbi, fb) = chunk.next().unwrap();
let (last_block_index, _last_block) = chunk.last().unwrap_or((fbi, fb));
let c_block = LBlock {
start: fbi,
end: last_block_index + 1,
};
free_mem.push(c_block);
} else {
for (_file_id, mut chunk) in &chunk.chunk_by(|(_i, block)| block.file_id()) {
let (fbi, fb) = chunk.next().unwrap();
let (lbi, _last_block) = chunk.last().unwrap_or((fbi, fb));
let c_block = LBlock {
start: fbi,
end: lbi + 1,
};
files.push(c_block);
}
};
}
for file in files.into_iter().rev() {
let size = file.len();
let Some((free_index, _)) = free_mem
.iter()
.find_position(|block| block.len() >= size && block.start < file.start)
else {
continue;
};
let free_mem_block = &mut free_mem[free_index];
for (file_index, free_index) in
(file.start..file.end).zip(free_mem_block.start..free_mem_block.end)
{
data.swap(file_index, free_index);
}
free_mem_block.start += file.len();
}
println!("{}", checksum(&data));
}

View File

@ -6,6 +6,7 @@ mod day5;
mod day6; mod day6;
mod day7; mod day7;
mod day8; mod day8;
mod day9;
use std::{ use std::{
fs::File, fs::File,
@ -23,6 +24,6 @@ fn parse_line(line: &str, pattern: char) -> impl Iterator<Item = i32> + '_ {
} }
fn main() { fn main() {
day8::task1(); day9::task1();
day8::task2(); day9::task2();
} }