2022-12-08 01:03:26 +00:00
|
|
|
#![allow(dead_code)]
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io;
|
|
|
|
use std::io::BufRead;
|
|
|
|
use std::path::Path;
|
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let now = Instant::now();
|
|
|
|
part_one();
|
|
|
|
let part_one_duration = now.elapsed();
|
|
|
|
part_two();
|
|
|
|
let part_two_duration = now.elapsed();
|
|
|
|
println!(
|
|
|
|
"p1: {}ms, p2: {}ms",
|
|
|
|
part_one_duration.as_millis(),
|
|
|
|
(part_two_duration - part_one_duration).as_millis()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
|
|
|
where
|
|
|
|
P: AsRef<Path>,
|
|
|
|
{
|
|
|
|
// note that this discards a final newline
|
|
|
|
let file = File::open(filename)?;
|
|
|
|
Ok(io::BufReader::new(file).lines())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn part_one() {
|
|
|
|
if let Ok(lines) = read_lines("./inputs/input") {
|
2022-12-08 03:07:18 +00:00
|
|
|
let mut sum = 0;
|
|
|
|
let mut stack: Vec<u32> = vec![0];
|
2022-12-08 01:03:26 +00:00
|
|
|
for line in lines {
|
|
|
|
if let Ok(command) = line {
|
|
|
|
match command.as_str() {
|
2022-12-08 03:07:18 +00:00
|
|
|
"$ cd /" => continue, // skip start
|
2022-12-08 01:03:26 +00:00
|
|
|
"$ ls" => continue, // we can assume this if we're not moving between directories
|
2022-12-08 03:07:18 +00:00
|
|
|
s if s.starts_with("dir ") => continue, // we'll get there when we `cd`
|
2022-12-08 01:03:26 +00:00
|
|
|
"$ cd .." => {
|
2022-12-08 03:07:18 +00:00
|
|
|
let f = stack.pop().unwrap();
|
|
|
|
if f < 100000 {
|
|
|
|
sum += f
|
|
|
|
}
|
2022-12-08 03:16:15 +00:00
|
|
|
let last_on_stack = stack.len() - 1;
|
|
|
|
stack[last_on_stack] += f;
|
2022-12-08 01:03:26 +00:00
|
|
|
}
|
|
|
|
s if s.starts_with("$ cd ") => {
|
2022-12-08 03:07:18 +00:00
|
|
|
stack.push(0);
|
2022-12-08 01:03:26 +00:00
|
|
|
}
|
|
|
|
s => {
|
|
|
|
// otherwise it must be a file
|
2022-12-08 03:07:18 +00:00
|
|
|
let mut sp = s.split(" ");
|
2022-12-08 03:16:15 +00:00
|
|
|
let last_on_stack = stack.len() - 1;
|
|
|
|
stack[last_on_stack] += sp.next().unwrap().parse::<u32>().unwrap();
|
2022-12-08 01:03:26 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2022-12-08 03:07:18 +00:00
|
|
|
println!("{:?}", sum);
|
2022-12-08 01:03:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-08 03:12:24 +00:00
|
|
|
fn part_two() {
|
|
|
|
if let Ok(lines) = read_lines("./inputs/input") {
|
|
|
|
let mut stack: Vec<u32> = vec![0];
|
|
|
|
let space_to_free = 30000000 - (70000000 - 49192532); // size of all files, precomputed
|
2022-12-08 03:18:08 +00:00
|
|
|
let mut to_delete = 70000000; // arbitrarily large
|
2022-12-08 03:12:24 +00:00
|
|
|
for line in lines {
|
|
|
|
if let Ok(command) = line {
|
|
|
|
match command.as_str() {
|
|
|
|
"$ cd /" => continue, // skip start
|
|
|
|
"$ ls" => continue, // we can assume this if we're not moving between directories
|
|
|
|
s if s.starts_with("dir ") => continue, // we'll get there when we `cd`
|
|
|
|
"$ cd .." => {
|
|
|
|
let f = stack.pop().unwrap();
|
|
|
|
if f > space_to_free && f < to_delete {
|
|
|
|
to_delete = f
|
|
|
|
}
|
2022-12-08 03:16:15 +00:00
|
|
|
let last_on_stack = stack.len() - 1;
|
|
|
|
stack[last_on_stack] += f;
|
2022-12-08 03:12:24 +00:00
|
|
|
}
|
|
|
|
s if s.starts_with("$ cd ") => {
|
|
|
|
stack.push(0);
|
|
|
|
}
|
|
|
|
s => {
|
|
|
|
// otherwise it must be a file
|
|
|
|
let mut sp = s.split(" ");
|
2022-12-08 03:16:15 +00:00
|
|
|
let last_on_stack = stack.len() - 1;
|
|
|
|
stack[last_on_stack] += sp.next().unwrap().parse::<u32>().unwrap();
|
2022-12-08 03:12:24 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
println!("{:?}", to_delete);
|
|
|
|
}
|
|
|
|
}
|