Day 7
authorGreg Burri <greg.burri@gmail.com>
Wed, 7 Dec 2022 22:38:59 +0000 (23:38 +0100)
committerGreg Burri <greg.burri@gmail.com>
Wed, 7 Dec 2022 22:38:59 +0000 (23:38 +0100)
Cargo.toml
src/day02.rs
src/day07.rs [new file with mode: 0644]
src/main.rs

index 0d0f199..3e0b2fe 100644 (file)
@@ -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
index cebdb21..1094862 100644 (file)
@@ -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 (file)
index 0000000..c3f5fb1
--- /dev/null
@@ -0,0 +1,125 @@
+use std::str::Lines;
+
+#[derive(Debug)]
+pub struct Dir {
+    files: Vec<i64>,
+    dirs: Vec<Dir>,
+}
+
+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<P>(&self, predicate: P, result: &mut Vec<i64>) -> i64
+    where
+        P: Fn(i64) -> bool + Copy,
+    {
+        let size = self.get_file_size() + self.dirs.iter().map(|dir| dir.dir_sizes(predicate, result)).sum::<i64>();
+        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<i64> = Vec::new();
+        root.dir_sizes(|size| size <= 100_000, &mut sizes);
+        assert_eq!(sizes.iter().sum::<i64>(), 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<i64> = Vec::new();
+        root.dir_sizes(|size| size >= required, &mut sizes);
+
+        assert_eq!(*sizes.iter().min().unwrap(), 24933642);
+    }
+}
\ No newline at end of file
index 056e7f5..91e1c7a 100644 (file)
@@ -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<i64> = Vec::new();
+        (root.dir_sizes(|size| size <= 100_000, &mut sizes), sizes.iter().sum::<i64>())
+    };
+
+    let min_part2 = {
+        let to_free = root_size - (70_000_000 - 30_000_000);
+        let mut sizes: Vec<i64> = 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<String> = env::args().skip(1).collect();