diff --git a/2022/src/day7.rs b/2022/src/day7.rs index 11cba3c..bb8c2f0 100644 --- a/2022/src/day7.rs +++ b/2022/src/day7.rs @@ -6,7 +6,7 @@ use nom::{ }, combinator::eof, multi::many0, - sequence::{self, terminated}, + sequence::terminated, IResult, Parser, }; use std::{ @@ -21,7 +21,7 @@ pub fn part1() -> String { } pub fn part2() -> String { - unimplemented!() + format!("{}", find_minimum_directory(&input(INPUT)).1) } #[derive(Clone, Debug, PartialEq)] @@ -66,6 +66,18 @@ fn tree_sizes_100k(filesystem: &Filesystem) -> usize { .fold(0, |cur, size| cur + size) } +fn find_minimum_directory(filesystem: &Filesystem) -> (PathBuf, usize) { + let needed_space = 30000000 - filesystem.free_space(); + let mut dir_sizes = filesystem + .find_dirs() + .iter() + .map(|path| (path.clone(), filesystem.size(path))) + .filter(|(_, size)| needed_space < (*size).try_into().unwrap()) + .collect::>(); + dir_sizes.sort_by(|(_, lsize), (_, rsize)| lsize.cmp(rsize)); + dir_sizes[0].clone() +} + #[derive(Clone, Debug, PartialEq)] enum Command { CD(String), @@ -113,6 +125,10 @@ impl Filesystem { .cloned() .collect() } + + fn free_space(&self) -> usize { + 70000000 - self.size(&PathBuf::from("/")) + } } impl Default for Filesystem { @@ -145,10 +161,6 @@ impl Default for State { } impl State { - fn paths(&self) -> HashSet { - self.filesystem.paths() - } - fn interpret_line(&mut self, line: SessionLine) { match line { SessionLine::Output(entry) => self.add_entry(entry), @@ -513,4 +525,19 @@ $ ls fn it_solves_part1() { assert_eq!(tree_sizes_100k(&input(INPUT)), 1792222); } + + #[test] + fn it_measures_free_space() { + with_input(|fs| assert_eq!(fs.free_space(), 21618835)); + } + + #[test] + fn it_finds_smallest_needed_dir() { + with_input(|fs| assert_eq!(find_minimum_directory(&fs), (PathBuf::from("/d"), 24933642))); + } + + #[test] + fn it_solves_part2() { + assert_eq!(find_minimum_directory(&input(INPUT)).1, 1112963); + } }