From 1df04702a2ec15500bf76ac7f1214f9804015df0 Mon Sep 17 00:00:00 2001 From: Gabe Venberg Date: Fri, 17 Nov 2023 23:52:42 -0600 Subject: [PATCH] parsing to a tree, ugly tree traversal. --- src/day07/file_tree.rs | 138 ++++++++++++++++++++++++++++++----------- src/day07/parser.rs | 91 ++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 38 deletions(-) diff --git a/src/day07/file_tree.rs b/src/day07/file_tree.rs index 990bea8..6d54f6e 100644 --- a/src/day07/file_tree.rs +++ b/src/day07/file_tree.rs @@ -22,7 +22,7 @@ pub enum FileTreeError { type WeakNodeRef = Weak>; #[derive(Debug)] -pub struct NodeRef(Rc>); +pub struct NodeRef(pub Rc>); impl Deref for NodeRef { type Target = Rc>; @@ -44,7 +44,7 @@ impl From for Rc> { } } -impl Display for NodeRef{ +impl Display for NodeRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.borrow()) } @@ -55,6 +55,28 @@ impl NodeRef { node.set_parent(self); self.borrow_mut().add_children(node) } + pub fn new_dir(name: String) -> NodeRef { + NodeRef(Rc::new(RefCell::new(Node::new_dir(name)))) + } + pub fn add_file(&mut self, name: String, size: usize) -> Result { + self.add_node(Node::new_file(name, size)) + } + pub fn add_dir(&mut self, name: String) -> Result { + self.add_node(Node::new_dir(name)) + } + pub fn get_all_dirs(&self) -> Vec { + let mut ret = Vec::new(); + match &self.borrow().contents { + Contents::Size(_) => {} + Contents::Children(c) => { + ret.push(NodeRef(Rc::clone(self))); + for node in c { + ret.append(&mut node.get_all_dirs()) + } + } + }; + ret + } } #[derive(Debug)] @@ -161,7 +183,7 @@ impl Node { } } -impl Display for Node{ +impl Display for Node { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "- {} {}", self.name, self.contents) } @@ -197,43 +219,87 @@ mod tests { #[test] fn test_dir_construction() { - let mut root = NodeRef(Rc::new(RefCell::new(Node::new_dir("/".to_string())))); + let mut root = NodeRef::new_dir("/".to_string()); let mut cursor = root.add_node(Node::new_dir("a".to_string())).unwrap(); - cursor = cursor.add_node(Node::new_dir("e".to_string())).unwrap(); - cursor - .add_node(Node::new_file("i".to_string(), 584)) - .unwrap(); + cursor = cursor.add_dir("e".to_string()).unwrap(); + cursor.add_file("i".to_string(), 584).unwrap(); cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); - cursor - .add_node(Node::new_file("f".to_string(), 29116)) - .unwrap(); - cursor - .add_node(Node::new_file("g".to_string(), 2557)) - .unwrap(); - cursor - .add_node(Node::new_file("h.lst".to_string(), 62596)) - .unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); - cursor - .add_node(Node::new_file("b.txt".to_string(), 14848514)) - .unwrap(); - cursor - .add_node(Node::new_file("c.dat".to_string(), 8504156)) - .unwrap(); - cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap(); - cursor - .add_node(Node::new_file("j".to_string(), 4060174)) - .unwrap(); - cursor - .add_node(Node::new_file("d.log".to_string(), 8033020)) - .unwrap(); - cursor - .add_node(Node::new_file("d.ext".to_string(), 5626152)) - .unwrap(); - cursor - .add_node(Node::new_file("k".to_string(), 7214296)) - .unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_dir("d".to_string()).unwrap(); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165); println!("{}", root); } + + #[test] + fn test_size_calcs() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut dirs: Vec = Vec::new(); + let mut cursor = root.add_dir("a".to_string()).unwrap(); + dirs.push(NodeRef(Rc::clone(&cursor))); + cursor = cursor.add_dir("e".to_string()).unwrap(); + dirs.push(NodeRef(Rc::clone(&cursor))); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap(); + dirs.push(NodeRef(Rc::clone(&cursor))); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165); + assert_eq!(Rc::clone(dirs[0].deref()).borrow().get_total_size(), 94853); + assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 584); + assert_eq!( + Rc::clone(dirs[2].deref()).borrow().get_total_size(), + 24933642 + ); + } + #[test] + fn test_get_all_dirs() { + let mut root = NodeRef::new_dir("/".to_string()); + let mut cursor = root.add_dir("a".to_string()).unwrap(); + cursor = cursor.add_dir("e".to_string()).unwrap(); + cursor.add_file("i".to_string(), 584).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("f".to_string(), 29116).unwrap(); + cursor.add_file("g".to_string(), 2557).unwrap(); + cursor.add_file("h.lst".to_string(), 62596).unwrap(); + cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(); + cursor.add_file("b.txt".to_string(), 14848514).unwrap(); + cursor.add_file("c.dat".to_string(), 8504156).unwrap(); + cursor = cursor.add_node(Node::new_dir("d".to_string())).unwrap(); + cursor.add_file("j".to_string(), 4060174).unwrap(); + cursor.add_file("d.log".to_string(), 8033020).unwrap(); + cursor.add_file("d.ext".to_string(), 5626152).unwrap(); + cursor.add_file("k".to_string(), 7214296).unwrap(); + let dirs = root.get_all_dirs(); + let sizes: Vec = dirs.iter().map(|d| d.borrow().get_total_size()).collect(); + println!("{:?}", sizes); + assert_eq!(Rc::clone(root.deref()).borrow().get_total_size(), 48381165); + assert_eq!( + Rc::clone(dirs[0].deref()).borrow().get_total_size(), + 48381165 + ); + assert_eq!(Rc::clone(dirs[1].deref()).borrow().get_total_size(), 94853); + assert_eq!(Rc::clone(dirs[2].deref()).borrow().get_total_size(), 584); + assert_eq!( + Rc::clone(dirs[3].deref()).borrow().get_total_size(), + 24933642 + ); + } } diff --git a/src/day07/parser.rs b/src/day07/parser.rs index f9bf84c..3be66d7 100644 --- a/src/day07/parser.rs +++ b/src/day07/parser.rs @@ -1,4 +1,7 @@ #![allow(unused)] +use std::ops::Deref; +use std::{cell::RefCell, rc::Rc}; + use crate::file_tree::*; use once_cell::sync::Lazy; use regex::Regex; @@ -77,8 +80,29 @@ pub fn parse(input: &str) -> Node { unimplemented!() } -pub fn commands_to_tree(input: Vec) -> Node { - unimplemented!() +pub fn commands_to_tree(input: Vec) -> NodeRef { + let root = NodeRef::new_dir("/".to_string()); + let mut cursor = NodeRef(Rc::clone(&root)); + for command in input { + match command { + Command::CdRoot => cursor = NodeRef(Rc::clone(&root)), + Command::CdUp => cursor = Rc::clone(cursor.deref()).borrow().get_parent().unwrap(), + Command::Cd(name) => cursor = cursor.add_dir(name).unwrap(), + Command::Ls(ls) => { + for entry in ls { + match entry { + LsEntry::Dir(d) => { + //dirs dont exist until you cd into them. + } + LsEntry::File(f) => { + cursor.add_file(f.name, f.size); + } + }; + } + } + } + } + root } #[cfg(test)] @@ -173,4 +197,67 @@ mod tests { ] ) } + #[test] + fn test_commands_to_tree() { + let input = vec![ + Command::CdRoot, + Command::Ls(vec![ + LsEntry::Dir(String::from("a")), + LsEntry::File(ParseFile { + size: 14848514, + name: String::from("b.txt"), + }), + LsEntry::File(ParseFile { + size: 8504156, + name: String::from("c.dat"), + }), + LsEntry::Dir(String::from("d")), + ]), + Command::Cd(String::from("a")), + Command::Ls(vec![ + LsEntry::Dir(String::from("e")), + LsEntry::File(ParseFile { + size: 29116, + name: String::from("f"), + }), + LsEntry::File(ParseFile { + size: 2557, + name: String::from("g"), + }), + LsEntry::File(ParseFile { + size: 62596, + name: String::from("h.lst"), + }), + ]), + Command::Cd(String::from("e")), + Command::Ls(vec![LsEntry::File(ParseFile { + size: 584, + name: String::from("i"), + })]), + Command::CdUp, + Command::CdUp, + Command::Cd(String::from("d")), + Command::Ls(vec![ + LsEntry::File(ParseFile { + size: 4060174, + name: String::from("j"), + }), + LsEntry::File(ParseFile { + size: 8033020, + name: String::from("d.log"), + }), + LsEntry::File(ParseFile { + size: 5626152, + name: String::from("d.ext"), + }), + LsEntry::File(ParseFile { + size: 7214296, + name: String::from("k"), + }), + ]), + ]; + let tree = commands_to_tree(input); + println!("{}", tree); + assert_eq!(Rc::clone(tree.deref()).borrow().get_total_size(), 48381165) + } }