From c10b78d032f8e2acf091a29e09ad0b8e0f3c845a Mon Sep 17 00:00:00 2001 From: Brandon Scott Date: Mon, 2 Jan 2023 00:43:38 -0600 Subject: [PATCH] Add Day 7 solution --- rust/src/day7.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++++ rust/src/main.rs | 2 + 2 files changed, 125 insertions(+) create mode 100644 rust/src/day7.rs diff --git a/rust/src/day7.rs b/rust/src/day7.rs new file mode 100644 index 0000000..7f089b3 --- /dev/null +++ b/rust/src/day7.rs @@ -0,0 +1,123 @@ +use std::collections::{HashMap, VecDeque}; +use std::fs::File; +use std::io::BufRead; +use std::io::BufReader; +use std::str; + +#[derive(Debug)] +struct FsNode { + name: String, + is_dir: bool, + size: u64, + sub_items: HashMap +} + +pub fn run() { + let file = File::open("resources/day7input.txt").expect("Input file not found."); + let reader = BufReader::new(file); + + let mut current_dir = VecDeque::from([String::from("_")]); + let mut root_node = FsNode { + name: String::from("_"), + is_dir: true, + size: 0, + sub_items: HashMap::new() + }; + + let mut current_node = &mut root_node; + + for line in reader.lines() { + let linex = line.unwrap(); + let parts: Vec<&str> = linex.split_whitespace().collect(); + if parts[0] == "$" { + match parts[1] { + "cd" => { + let dir = parts[2]; + if dir == "/" { + current_dir = VecDeque::from([String::from("_")]); + current_node = &mut root_node; + } else if dir == ".." { + current_dir.pop_back(); + current_node = find_node_by_path(&mut root_node,VecDeque::from(current_dir.clone())).unwrap(); + } else { + current_dir.push_back(String::from(dir)); + current_node = current_node.sub_items.get_mut(dir).unwrap(); + } + } + "ls" => {} + _ => eprintln!("error: invalid command {:?}", parts[1]) + } + } else if parts[0] == "dir" { + current_node.sub_items.insert(String::from(parts[1]),FsNode { + name: String::from(parts[1]), + is_dir: true, + size: 0, + sub_items: HashMap::new() + }); + } else { + current_node.sub_items.insert(String::from(parts[1].to_string()),FsNode { + name: String::from(parts[1].to_string()), + is_dir: false, + size: parts[0].parse::().unwrap(), + sub_items: HashMap::new() + }); + } + } + + let mut sizes:Vec = Vec::new(); + let mut sum: u64 = 0; + let mut answer2: u64 = 0; + let fs_size: u64 = 70000000; + let fs_min_space: u64 = 30000000; + let used_space = calculate_dir_sizes(&root_node, &mut sizes); + let free_space = fs_size-used_space; + println!("used space: {:?}", used_space); + println!("free space: {:?}", free_space); + + sizes.sort(); + for x in sizes { + if x <= 100000 { + sum += x; + } + if answer2 == 0 && free_space+x >= fs_min_space { + answer2 = x; + } + } + + println!("Day 7 Answer 1: {:?}", sum); + println!("Day 7 Answer 2: {:?}", answer2); +} + +fn find_node_by_path(node: &mut FsNode, mut path: VecDeque) -> Option<&mut FsNode> { + let name = path.pop_front()?; // Return None if the path is empty + if path.len() == 0 && name == "_" { + return Some(node); + } + if name == "_" { + return find_node_by_path(node, path); + } + if let Some(sub_item) = node.sub_items.get_mut(name.as_str()) { + return if path.len() == 0 && sub_item.name == name && sub_item.is_dir { + Some(sub_item) + } else { + find_node_by_path(sub_item, path) + } + } + None +} + +fn calculate_dir_sizes(node: &FsNode, dir_sizes: &mut Vec) -> u64 { + let mut sum: u64 = 0; + if node.sub_items.len() > 0 { + for (_, sub_node) in &node.sub_items { + if sub_node.is_dir { + let size = calculate_dir_sizes(sub_node, dir_sizes); + sum += size; + dir_sizes.push(size); + } else { + sum += sub_node.size; + } + } + } + sum +} \ No newline at end of file diff --git a/rust/src/main.rs b/rust/src/main.rs index 48dee69..6243a70 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -6,6 +6,7 @@ mod day3; mod day4; mod day5; mod day6; +mod day7; fn main() { let args: Vec = env::args().collect(); @@ -19,6 +20,7 @@ fn main() { "day4" => day4::run(), "day5" => day5::run(), "day6" => day6::run(), + "day7" => day7::run(), _ => eprintln!("error: invalid day") } },