diff --git a/day07/Cargo.lock b/day07/Cargo.lock new file mode 100644 index 0000000..cf14c74 --- /dev/null +++ b/day07/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day07" +version = "0.1.0" diff --git a/day07/Cargo.toml b/day07/Cargo.toml new file mode 100644 index 0000000..682e4ad --- /dev/null +++ b/day07/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day07" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day07/src/main.rs b/day07/src/main.rs new file mode 100644 index 0000000..ad37050 --- /dev/null +++ b/day07/src/main.rs @@ -0,0 +1,160 @@ +use std::cell::RefCell; +use std::error; +use std::fs::File; +use std::io::BufRead; +use std::io::BufReader; +use std::rc::{Rc, Weak}; + + +enum FsEntry { + Dir(Rc), + File(FsFile) +} + +struct FsDir { + name: String, + children: RefCell>, + parent: Option> +} + +impl FsDir { + fn _compute_size(&self) -> u32 { + let mut size: u32 = 0; + let children = self.children.borrow_mut(); + for child in children.iter() { + match child { + FsEntry::File(f) => size += f.size, + FsEntry::Dir(d) => { + size += d._compute_size(); + }, + }; + } + size + } + + fn _show(&self, prefix: String) { + println!("{}{}", &prefix, &self.name); + let children = self.children.borrow_mut(); + for child in children.iter() { + match child { + FsEntry::File(f) => println!("{}{}", &prefix, &f.size), + FsEntry::Dir(d) => d._show(format!("{} ", &prefix)), + }; + } + } + + fn get_dir_sizes(&self) -> Vec { + let mut sizes = vec![]; + let mut size: u32 = 0; + let children = self.children.borrow_mut(); + for child in children.iter() { + match child { + FsEntry::File(f) => size += f.size, + FsEntry::Dir(d) => { + let d_vec = d.get_dir_sizes(); + size += d_vec[d_vec.len() - 1]; + sizes.extend_from_slice(&d_vec); + }, + }; + } + sizes.push(size); + sizes + } +} + +struct FsFile { + size: u32 +} + +fn main() -> Result<(), Box> { + let f = File::open("input.txt")?; + let reader = BufReader::new(f); + + let fs_tree: Rc = Rc::new(FsDir { children: RefCell::new(vec![]), parent: None, name: String::from("/") }); + let mut current_dir = Rc::downgrade(&fs_tree); + + for line in reader.lines() { + let line = line?; + if &line[0..1] == "$" { + // parse the command + let mut cmd_iter = line[2..].split_whitespace(); + match cmd_iter.next() { + Some("cd") => { + // println!("{}", &line); + match cmd_iter.next() { + Some("/") => current_dir = Rc::downgrade(&fs_tree), + Some("..") => { + let mut new_dir = None; + let strong = current_dir.upgrade().unwrap(); + match &strong.parent { + Some(x) => { + let strong_x = x.upgrade().unwrap(); + let rc_c = Rc::clone(&strong_x); + new_dir = Some(Rc::downgrade(&rc_c)); + }, + None => (), + }; + match new_dir { + Some(d) => current_dir = d, + None => panic!("Could not find parent dir in '{}'", current_dir.upgrade().unwrap().name), + }; + }, + Some(x) => { + let mut new_dir = None; + let strong = current_dir.upgrade().unwrap(); + let children = strong.children.borrow_mut(); + for child in children.iter() { + if let FsEntry::Dir(d) = child { + if d.name == x { + new_dir = Some(Rc::clone(&d)); + break; + } + } + } + match new_dir { + Some(d) => current_dir = Rc::downgrade(&d), + None => panic!("Could not find dir '{x}' in '{}'", current_dir.upgrade().unwrap().name), + } + }, + None => panic!("No argument to 'cd': {}", line), + }; + // println!("{}", current_dir.upgrade().unwrap().name); + }, + Some("ls") => { + // we can ignore this, as we read everything not being a command into the + // current directory anyways + } + Some(x) => panic!("Unsupported command: {}", x), + None => panic!("Could not split into a command: {}", line), + }; + } else { + // parse the list of fs entries + let mut entry_iter = line.split_whitespace(); + match entry_iter.next() { + Some("dir") => { + let new_dir = Rc::new(FsDir {name: String::from(entry_iter.next().unwrap()), + children: RefCell::new(vec![]), parent: Some(current_dir.clone()) }); + let strong = current_dir.upgrade().unwrap(); + let mut children = strong.children.borrow_mut(); + children.push(FsEntry::Dir(new_dir)); + }, + Some(size) => { + let f = FsFile {size: size.parse().unwrap()}; + let strong = current_dir.upgrade().unwrap(); + let mut children = strong.children.borrow_mut(); + children.push(FsEntry::File(f)); + }, + _ => panic!("Unknown fs entry: {line}"), + }; + } + } + drop(current_dir); + // fs_tree.show(String::from("")); + + // compute sizes + let sizes = fs_tree.get_dir_sizes(); + println!("{}", sizes.iter().filter(|x| **x < 100000).sum::()); + + println!("Hello, world!"); + Ok(()) +}