Day 9
This commit is contained in:
parent
cc04168468
commit
ec647002cd
137
src/day9.rs
Normal file
137
src/day9.rs
Normal 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));
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user