summaryrefslogtreecommitdiff
path: root/aoc22/day7/src/main.rs
diff options
context:
space:
mode:
authormathiasmagnusson <mathias@magnusson.space>2022-12-11 23:04:39 +0100
committermathiasmagnusson <mathias@magnusson.space>2022-12-11 23:04:39 +0100
commitb7e2fe6160280472a625a8867ea5177b0155737c (patch)
treef8b10bd9a20adbd568b3a0d75fc0367a0523107f /aoc22/day7/src/main.rs
parentac1f723d39b6d25903237af86a7319209373731b (diff)
downloadprogramming-problem-solving-b7e2fe6160280472a625a8867ea5177b0155737c.tar.gz
Aoc day 6, 7 & 8
Diffstat (limited to 'aoc22/day7/src/main.rs')
-rw-r--r--aoc22/day7/src/main.rs122
1 files changed, 122 insertions, 0 deletions
diff --git a/aoc22/day7/src/main.rs b/aoc22/day7/src/main.rs
new file mode 100644
index 0000000..09dbd8a
--- /dev/null
+++ b/aoc22/day7/src/main.rs
@@ -0,0 +1,122 @@
+use std::collections::HashMap;
+
+fn main() {
+ let input = lib::read_input(7);
+
+ part1(&input);
+ part2(&input);
+}
+
+fn part1(input: &str) {
+ let fs = parse(input);
+
+ let ans: u32 = fs
+ .iter()
+ .enumerate()
+ .filter(|(_, f)| matches!(f, Node::Dir { .. }))
+ .map(|(i, _)| get_size(&fs, i))
+ .filter(|&s| s <= 100_000)
+ .sum();
+
+ println!("{}", ans);
+}
+
+fn part2(input: &str) {
+ let fs = parse(input);
+
+ let used = get_size(&fs, 0);
+ let free = 70_000_000 - used;
+ let to_free = 30_000_000 - free;
+
+ let ans = fs
+ .iter()
+ .enumerate()
+ .flat_map(|(i, f)| match f {
+ Node::Dir { .. } => Some(get_size(&fs, i)),
+ _ => None,
+ })
+ .filter(|&s| s >= to_free)
+ .min_by_key(|&s| s)
+ .unwrap();
+
+ println!("{:?}", ans);
+}
+
+fn get_size<'a>(fs: &Vec<Node<'a>>, index: usize) -> u32 {
+ match &fs[index] {
+ Node::Dir { contents, .. } => contents.values().map(|&i| get_size(fs, i)).sum::<u32>(),
+ &Node::File { size, .. } => size,
+ }
+}
+
+#[derive(Debug)]
+enum Node<'a> {
+ Dir {
+ parent: usize,
+ contents: HashMap<&'a str, usize>,
+ name: &'a str,
+ },
+ File {
+ size: u32,
+ name: &'a str,
+ },
+}
+
+impl<'a> Node<'a> {
+ fn parent(&self) -> usize {
+ match self {
+ Node::Dir { parent, .. } => *parent,
+ Node::File { .. } => panic!("File has no parent"),
+ }
+ }
+ fn contents(&mut self) -> &mut HashMap<&'a str, usize> {
+ match self {
+ Node::Dir { contents, .. } => contents,
+ Node::File { .. } => panic!("File has no contents"),
+ }
+ }
+}
+
+fn parse<'a>(input: &'a str) -> Vec<Node<'a>> {
+ let mut dirs = vec![Node::Dir {
+ parent: 0,
+ contents: HashMap::new(),
+ name: "/",
+ }];
+ let mut curr = 0;
+ for line in input.lines() {
+ let s = line.split_whitespace().collect::<Vec<_>>();
+ if s[0] == "$" {
+ match s[1] {
+ "cd" => {
+ if s[2] == "/" {
+ curr = 0;
+ } else if s[2] == ".." {
+ curr = dirs[curr].parent();
+ } else {
+ curr = dirs[curr].contents()[s[2]];
+ }
+ }
+ _ => {}
+ }
+ } else if s[0] == "dir" {
+ let name = s[1];
+ let node = Node::Dir {
+ parent: curr,
+ contents: HashMap::new(),
+ name,
+ };
+ let idx = dirs.len();
+ dirs.push(node);
+ dirs[curr].contents().insert(name, idx);
+ } else {
+ let size = s[0].parse().unwrap();
+ let name = s[1];
+ let node = Node::File { size, name };
+ let idx = dirs.len();
+ dirs.push(node);
+ dirs[curr].contents().insert(name, idx);
+ }
+ }
+ dirs
+}