From a3bb8ad37af4ec8254cf16ae2ee60323323b3198 Mon Sep 17 00:00:00 2001 From: nekineki Date: Mon, 9 Dec 2024 07:14:44 +0100 Subject: day09 --- 2024/day09.rs | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 2024/day09.rs (limited to '2024/day09.rs') diff --git a/2024/day09.rs b/2024/day09.rs new file mode 100644 index 0000000..986bf74 --- /dev/null +++ b/2024/day09.rs @@ -0,0 +1,172 @@ +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_mut)] +use std::env; +use std::fs::File; +use std::io::Read; + +#[derive(Debug, PartialEq, Clone)] +struct Block { + isfile: bool, + id: u64, +} + +fn print_fs(fs: &Vec) { + for b in fs { + if b.isfile { + print!("{}", b.id); + } else { + print!("."); + } + } + println!(); +} + +fn compact(mut fs: Vec) -> Vec { + for i in (0..fs.len()).rev() { + if !fs[i].isfile { + continue; + } + for j in 0..fs.len() { + if i < j { + break; + } + if !fs[j].isfile { + fs.swap(i, j); + break; + } + } + } + fs +} + +fn same(index: usize, fs: &Vec) -> (usize, usize) { + let mut start: usize = 0; + let mut end: usize = 0; + let b = &fs[index]; + + for e in index..fs.len() { + if fs[e].isfile == b.isfile && (!fs[e].isfile || fs[e].id == b.id) { + end = e; + } else { + break; + } + } + + for s in (0..=index).rev() { + if fs[s].isfile == b.isfile && (!fs[s].isfile || fs[s].id == b.id) { + start = s; + } else { + break; + } + } + + return (start, end - start + 1); +} + +fn compact2(mut fs: Vec) -> Vec { + let mut i = fs.len() - 1; + loop { + let mut il; + (i, il) = same(i, &fs); + + if !fs[i].isfile { + if i == 0 { + break; + } + i -= 1; + continue; + } + + let mut j = 0; + let mut jl; + loop { + (j, jl) = same(j, &fs); + if j > i { + break; + } + if fs[j].isfile || il > jl { + if j + jl >= fs.len() { + break; + } + j = j + jl; + continue; + } + + for r in 0..il { + fs.swap(i + r, j + r); + } + + if j + jl >= fs.len() { + break; + } + j = j + jl; + } + + if i == 0 { + break; + } + i -= 1; + } + + fs +} + +fn checksum(fs: &Vec) -> u64 { + let mut sum = 0; + for i in (0..fs.len()).rev() { + if fs[i].isfile { + sum += (i as u64) * fs[i].id; + } + } + return sum; +} + +fn main() { + let args: Vec = env::args().collect(); + let filename = if args.len() == 1 { + "in/".to_owned() + args[0].split('/').last().unwrap() + ".pzl" + } else { + args[1].clone() + }; + let mut f = File::open(filename).expect("cannot open file"); + let mut content = String::new(); + f.read_to_string(&mut content).expect("cannot read file"); + let mut lines = content.trim_end().split("\n"); + + let line = lines.next().unwrap(); + + let mut fs: Vec = Vec::new(); + let mut isfile = true; + let mut id = 0; + for (i, c) in line.chars().enumerate() { + let n = c.to_digit(10).unwrap() as usize; + + for j in 0..n { + let b = Block { + isfile: isfile, + id: id, + }; + fs.push(b); + } + if isfile { + id += 1; + } + isfile ^= true; + } + + //print_fs(&fs); + let fs1 = compact(fs.clone()); + //print_fs(&fs1); + let res1 = checksum(&fs1); + + //print_fs(&fs); + let fs2 = compact2(fs.clone()); + //print_fs(&fs2); + let res2 = checksum(&fs2); + + println!("res1: {}", res1); + println!("res2: {}", res2); + assert_eq!(res1, 6370402949053); + assert_eq!(res2, 6398096697992); +} -- cgit v1.2.3