Skip to content

Instantly share code, notes, and snippets.

@saolsen
Created December 7, 2022 18:38
Show Gist options
  • Save saolsen/cd873808264a3c613d17de6db3a0e5b2 to your computer and use it in GitHub Desktop.
Save saolsen/cd873808264a3c613d17de6db3a0e5b2 to your computer and use it in GitHub Desktop.
aoc 2022 day07
use std::{collections::HashMap, iter::Peekable, str::Split};
#[derive(Debug)]
struct Dir<'a> {
path: Vec<&'a str>,
files: HashMap<&'a str, File<'a>>,
}
#[derive(Debug)]
struct File<'a> {
name: &'a str,
size: usize,
}
struct Shell<'a> {
dirs: HashMap<Vec<&'a str>, Dir<'a>>,
lines: Peekable<Split<'a, &'a str>>,
cwd: Vec<&'a str>,
}
impl<'a> Shell<'a> {
pub fn new(input: &'a str) -> Self {
let lines = input.split("\n").peekable();
let mut dirs = HashMap::new();
dirs.insert(
vec!["/"],
Dir {
path: vec!["/"],
files: HashMap::new(),
},
);
let cwd = vec![];
Shell { dirs, lines, cwd }
}
pub fn command(&mut self) -> bool {
if let Some(line) = self.lines.next() {
let mut split = line.split(" ");
assert_eq!(split.next(), Some("$"));
let command = split.next().unwrap();
match command {
"cd" => {
let dir_name = split.next().unwrap();
if dir_name == ".." {
self.cwd.pop();
} else {
self.cwd.push(dir_name);
}
}
"ls" => {
//let current_dir = &mut self.dirs[self.cwd];
let mut new_children = vec![];
let mut new_files = vec![];
loop {
if let Some(next_line) = self.lines.peek() {
if next_line.starts_with("$") {
break;
}
} else {
break;
}
let result = self.lines.next().unwrap();
let mut parts = result.split(" ");
let a = parts.next().unwrap();
let b = parts.next().unwrap();
if a == "dir" {
let mut path = self.cwd.clone();
path.push(b);
if !self.dirs.contains_key(&path) {
new_children.push(Dir {
path,
files: HashMap::new(),
})
}
} else {
if !self.dirs.get(&self.cwd).unwrap().files.contains_key(b) {
new_files.push(File {
name: b,
size: a.parse().unwrap(),
});
}
}
}
for c in new_children {
self.dirs.insert(c.path.clone(), c);
}
for f in new_files {
let cwd = self.dirs.get_mut(&self.cwd).unwrap();
cwd.files.insert(f.name, f);
}
}
_ => unimplemented!(),
}
true
} else {
false
}
}
pub fn dir_sizes(&self) -> HashMap<Vec<&'a str>, usize> {
let mut result = HashMap::new();
for path in self.dirs.keys() {
let mut sum = 0;
for (p, dir) in &self.dirs {
if p.starts_with(path) {
for (_, f) in &dir.files {
sum += f.size;
}
}
}
result.insert(path.clone(), sum);
}
result
}
pub fn run(&mut self) {
while self.command() {}
}
}
fn main() {
let mut shell = Shell::new(include_str!("day07_input.txt"));
shell.run();
let sizes = shell.dir_sizes();
// part 1
let mut total = 0;
for (_, s) in &sizes {
if *s <= 100000 {
total += *s;
}
}
eprintln!("total: {total}");
// part 2
let disk_space = 70000000;
let needed_free = 30000000;
let size_of_root = sizes.get(&vec!["/"]).unwrap();
let size_free = disk_space - size_of_root;
let still_need_to_free = needed_free - size_free;
let mut min_big_enough = usize::MAX;
for (_, s) in &sizes {
if *s > still_need_to_free && *s < min_big_enough {
min_big_enough = *s;
}
}
eprintln!("delete size: {min_big_enough}");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment