From 6ff8c8219c9b3916bf8d8002e6225f4a13a89410 Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Wed, 7 Dec 2022 23:38:59 +0100 Subject: [PATCH] Day 7 --- Cargo.toml | 3 -- src/day02.rs | 2 +- src/day07.rs | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 20 +++++++++ 4 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 src/day07.rs diff --git a/Cargo.toml b/Cargo.toml index 0d0f199..3e0b2fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,7 @@ edition = "2021" [dependencies] itertools = "0.10" -threadpool = "1.8" regex = "1" -num = "0.4" -num_enum = "0.5" [profile.release] opt-level = 3 diff --git a/src/day02.rs b/src/day02.rs index cebdb21..1094862 100644 --- a/src/day02.rs +++ b/src/day02.rs @@ -52,7 +52,7 @@ where let s1: Shape = Shape::parse(l[0]); let s2 = match l[1] { "X" => match s1 { Shape::Rock => Shape::Scissors, Shape::Paper => Shape::Rock, Shape::Scissors => Shape::Paper, }, // Need to lose. - "Z" => match s1 { Shape::Rock => Shape::Paper, Shape::Paper => Shape::Scissors, Shape::Scissors => Shape::Rock, }, // Need to win + "Z" => match s1 { Shape::Rock => Shape::Paper, Shape::Paper => Shape::Scissors, Shape::Scissors => Shape::Rock, }, // Need to win. _ => s1, // Draw. }; diff --git a/src/day07.rs b/src/day07.rs new file mode 100644 index 0000000..c3f5fb1 --- /dev/null +++ b/src/day07.rs @@ -0,0 +1,125 @@ +use std::str::Lines; + +#[derive(Debug)] +pub struct Dir { + files: Vec, + dirs: Vec, +} + +impl Dir { + fn new() -> Dir { + Dir { files: Vec::new(), dirs: Vec::new() } + } + + fn get_file_size(&self) -> i64 { + self.files.iter().sum() + } + + pub fn dir_sizes

(&self, predicate: P, result: &mut Vec) -> i64 + where + P: Fn(i64) -> bool + Copy, + { + let size = self.get_file_size() + self.dirs.iter().map(|dir| dir.dir_sizes(predicate, result)).sum::(); + if predicate(size) { + result.push(size) + } + size + } +} + +pub fn parse(input: &str) -> Dir { + fn create_dir(lines: &mut Lines) -> Dir { + let mut dir = Dir::new(); + while let Some(l) = lines.next() { + let l: Vec<&str> = l.split(' ').collect(); + if l[0] == "$" { + if l[1] == "cd" { + if l[2] == ".." { + return dir; + } else { + let child = create_dir(lines); + dir.dirs.push(child); + } + } + } else if l[0] != "dir" { + dir.files.push(l[0].parse().unwrap()); + } + } + dir + } + let mut lines = input.lines(); + lines.next(); // First line is always the root. + create_dir(&mut lines) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1() { + let commands = "$ cd / +$ ls +dir a +14848514 b.txt +8504156 c.dat +dir d +$ cd a +$ ls +dir e +29116 f +2557 g +62596 h.lst +$ cd e +$ ls +584 i +$ cd .. +$ cd .. +$ cd d +$ ls +4060174 j +8033020 d.log +5626152 d.ext +7214296 k"; + let root = parse(commands); + let mut sizes: Vec = Vec::new(); + root.dir_sizes(|size| size <= 100_000, &mut sizes); + assert_eq!(sizes.iter().sum::(), 95_437); + } + + #[test] + fn part2() { + let commands = "$ cd / +$ ls +dir a +14848514 b.txt +8504156 c.dat +dir d +$ cd a +$ ls +dir e +29116 f +2557 g +62596 h.lst +$ cd e +$ ls +584 i +$ cd .. +$ cd .. +$ cd d +$ ls +4060174 j +8033020 d.log +5626152 d.ext +7214296 k"; + let root = parse(commands); + + let root_size = root.dir_sizes(|size| size <= 100_000, &mut Vec::new()); + + let required = root_size - (70_000_000 - 30_000_000); + let mut sizes: Vec = Vec::new(); + root.dir_sizes(|size| size >= required, &mut sizes); + + assert_eq!(*sizes.iter().min().unwrap(), 24933642); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 056e7f5..91e1c7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod day03; mod day04; mod day05; mod day06; +mod day07; fn day01() -> String { let f = fs::File::open("data/day01.input").unwrap(); @@ -45,6 +46,24 @@ fn day06() -> String { format!("part1: {}, part2: {}", day06::first_marker_pos(&signals, 4), day06::first_marker_pos(&signals, 14)) } +fn day07() -> String { + let root = day07::parse(&fs::read_to_string("data/day07.input").unwrap()); + + let (root_size, sum_part1 ) = { + let mut sizes: Vec = Vec::new(); + (root.dir_sizes(|size| size <= 100_000, &mut sizes), sizes.iter().sum::()) + }; + + let min_part2 = { + let to_free = root_size - (70_000_000 - 30_000_000); + let mut sizes: Vec = Vec::new(); + root.dir_sizes(|size| size >= to_free, &mut sizes); + *sizes.iter().min().unwrap() + }; + + format!("part1: {}, part2: {}", sum_part1, min_part2) +} + fn format_micros(t: u128) -> String { if t < 10_000 { format!("{} μs", t) @@ -70,6 +89,7 @@ fn main() { day04, day05, day06, + day07, ); let args: Vec = env::args().skip(1).collect(); -- 2.45.2