/ Rust / 2022 / 07.rs
07.rs
 1  #![feature(test)]
 2  
 3  use rustc_hash::FxHashMap;
 4  
 5  type Input<'a> = Vec<Node<'a>>;
 6  
 7  struct Node<'a> {
 8      size: u64,
 9      parent_id: Option<usize>,
10      names: FxHashMap<&'a str, usize>,
11      visited: bool,
12  }
13  
14  impl Node<'_> {
15      fn new(parent_id: Option<usize>) -> Self {
16          Self {
17              size: 0,
18              parent_id,
19              names: FxHashMap::default(),
20              visited: false,
21          }
22      }
23  }
24  
25  fn setup(input: &str) -> Input {
26      let mut nodes = vec![Node::new(None)];
27      let mut pwd = 0;
28      let mut visiting = None;
29      for line in input.trim().lines() {
30          let mut split = line.split(' ');
31          match (split.next(), split.next(), split.next()) {
32              (Some("$"), Some("cd"), Some(dir)) => {
33                  if dir == "/" {
34                      pwd = 0;
35                  } else if dir == ".." {
36                      pwd = nodes[pwd].parent_id.unwrap_or(0)
37                  } else {
38                      pwd = match nodes[pwd].names.get(dir) {
39                          Some(id) => *id,
40                          None => {
41                              let id = nodes.len();
42                              nodes.push(Node::new(Some(pwd)));
43                              nodes[pwd].names.insert(dir, id);
44                              id
45                          }
46                      }
47                  }
48              }
49              (Some(size), Some(_), None) => {
50                  if let Ok(size) = size.parse::<u64>() {
51                      if nodes[pwd].visited {
52                          continue;
53                      }
54                      visiting = Some(pwd);
55                      nodes[pwd].size += size;
56                  }
57              }
58              _ => {
59                  if let Some(v) = visiting {
60                      nodes[v].visited = true;
61                      visiting = None;
62                  }
63              }
64          }
65      }
66      for i in (1..nodes.len()).rev() {
67          if let Node {
68              size,
69              parent_id: Some(parent_id),
70              ..
71          } = nodes[i]
72          {
73              nodes[parent_id].size += size;
74          }
75      }
76      nodes
77  }
78  
79  fn part1(nodes: &Input) -> u64 {
80      nodes
81          .iter()
82          .map(|node| node.size)
83          .filter(|x| *x <= 100000)
84          .sum()
85  }
86  
87  fn part2(nodes: &Input) -> u64 {
88      let free = 70000000 - nodes[0].size;
89      nodes
90          .iter()
91          .map(|node| node.size)
92          .filter(|x| *x >= 30000000 - free)
93          .min()
94          .unwrap()
95  }
96  
97  aoc::main!(2022, 7, ex: 1);