11use crate :: input_reader;
2- use std:: borrow:: BorrowMut ;
3- use std:: collections:: HashMap ;
4- use std:: cell:: RefCell ;
5- use std:: rc:: Rc ;
2+ use std:: { collections:: HashMap } ;
63
74struct File {
85 name : String ,
9- size : i32
6+ size : usize
107}
118
12- struct Dir {
13- parent : Option < String > ,
14- name : String ,
15- dirs : Vec < String > ,
16- files : Vec < File >
9+ fn finished_mapping (
10+ dirs : & Vec < Vec < & str > > ,
11+ dir_size : & HashMap < Vec < & str > , usize >
12+ ) -> bool {
13+ for dir in dirs {
14+ if !dir_size. contains_key ( dir) {
15+ return false ;
16+ }
17+ }
18+ return true ;
1719}
1820
19- // impl Hash for Dir {
20- // fn hash<H: Hasher>(&self, state: &mut H) {
21- // self.name.hash(state);
22- // }
23- // }
24-
25- // impl PartialEq for Dir {
26- // fn eq(&self, other: &Self) -> bool {
27- // self.name == other.name
28- // }
29- // }
30- // impl Eq for Dir {}
31-
32- impl Dir {
33- pub fn add_file ( & mut self , file : File ) {
34- self . files . push ( file)
21+ fn part1 (
22+ sub_dirs : HashMap < Vec < & str > , Vec < Vec < & str > > > ,
23+ files : HashMap < Vec < & str > , Vec < File > > ,
24+ root : Vec < & str >
25+ ) {
26+ let mut dir_size: HashMap < Vec < & str > , usize > = HashMap :: new ( ) ;
27+ let cursor: & mut Vec < & str > = & mut root. clone ( ) ;
28+
29+ ' map_sub_dir: while !finished_mapping ( sub_dirs. get ( & root. clone ( ) ) . unwrap ( ) , & dir_size) {
30+
31+ let mut sum: usize = 0 ;
32+
33+ // If there are sub_dirs, get the size of each sub_dir. If the size has
34+ // not been calculated, move the cursor into the map and restart the
35+ // count.
36+ for sub_dir in sub_dirs. get ( cursor) . unwrap ( ) {
37+ if dir_size. contains_key ( sub_dir) {
38+ sum += dir_size. get ( sub_dir) . unwrap ( ) ;
39+ } else {
40+ cursor. push ( sub_dir. last ( ) . unwrap ( ) ) ;
41+ continue ' map_sub_dir;
42+ }
43+ }
44+
45+ // Compute files
46+ for file in files. get ( cursor) . unwrap ( ) {
47+ sum += file. size ;
48+ }
49+ dir_size. insert ( cursor. clone ( ) , sum) ;
50+
51+ // Now that we've mapped this dir, let's continue mapping the
52+ // parent.
53+ cursor. pop ( ) ;
3554 }
3655
37- pub fn add_dir ( & mut self , dir : String ) {
38- self . dirs . push ( dir)
56+ let mut sum: usize = 0 ;
57+ for d in dir_size {
58+ if d. 1 <= 100000 {
59+ sum += d. 1 ;
60+ }
3961 }
62+
63+ println ! ( "Part 1: {}" , sum) ;
4064}
4165
4266pub fn run ( ) {
4367 let input = input_reader:: read_file_in_cwd ( "src/day_07.data" ) ;
4468
45- let root = Dir { parent : None , name : "/" . to_string ( ) , dirs : vec ! [ ] , files : vec ! [ ] } ;
46- let mut dirs: HashMap < & str , Rc < RefCell < Dir > > > = HashMap :: new ( ) ;
47- let mut current_dir_name = "/" ;
48- dirs. insert ( & current_dir_name, Rc :: new ( RefCell :: new ( root) ) ) ;
49-
69+ let mut dirs: HashMap < Vec < & str > , Vec < Vec < & str > > > = HashMap :: new ( ) ;
70+ let mut files: HashMap < Vec < & str > , Vec < File > > = HashMap :: new ( ) ;
71+ let mut path: Vec < & str > = vec ! [ ] ;
5072
5173 // Split the input "$". Each "$" represents an executed command.
5274 let command_and_outputs: Vec < & str > = input. split ( "$ " ) . collect ( ) ;
@@ -57,7 +79,7 @@ pub fn run() {
5779 // The split token will be blank, because the input starts with "$ ",
5880 // so we skip it.
5981 if command_and_output == "" {
60- return
82+ continue ;
6183 }
6284
6385 // The first line between each command execution is the command. The
@@ -70,42 +92,38 @@ pub fn run() {
7092 "cd" => {
7193 let new_dir_name = command_split[ 1 ] ;
7294
73- // Skip "/", as that's the initial state we are in.
74- if new_dir_name == "/" {
75- return ;
76- }
77-
7895 if new_dir_name == ".." {
79- let thing = dirs. get ( current_dir_name) . unwrap ( ) . borrow ( ) ;
80- current_dir_name = thing. parent . as_ref ( ) . unwrap ( ) . as_str ( ) ;
81- return ;
96+ path. pop ( ) ;
97+ continue ;
8298 }
8399
84- current_dir_name = new_dir_name
100+ path . push ( new_dir_name) ;
85101 } ,
86102 "ls" => {
103+ let mut dir_dirs = vec ! [ ] ;
104+ let mut dir_files = vec ! [ ] ;
87105 let items: Vec < & str > = output. split ( "\n " ) . collect ( ) ;
88106 // Using a casual iterator, because I don't know yet how to
89107 // handle mutables and closures at the same time...
90108 for i in 0 ..items. len ( ) {
91109 let item_info: Vec < & str > = items[ i] . split ( " " ) . collect ( ) ;
92110 if item_info[ 0 ] == "dir" {
93- let sub_dir_name = item_info[ 0 ] ;
94- // let sub_dir = &mut Dir { parent: Some(dir.to_string()), name: sub_dir_name.to_string(), dirs: vec![], files: vec![] };
95- let current_dir = dirs. get_mut ( current_dir_name) . unwrap ( ) . borrow_mut ( ) ;
96- //current_dir.add_dir(sub_dir_name.to_string());
97- let sub_dir = Box :: new ( & mut Dir { parent : None , name : "/" . to_string ( ) , dirs : vec ! [ ] , files : vec ! [ ] } ) ;
98- // let sub_dir = &mut Dir { parent: Some(current_dir_name.to_string()), name: sub_dir_name.to_string(), dirs: vec![], files: vec![] }
99- //dirs.insert(sub_dir_name, sub_dir);
100- } else {
101- let file_size = item_info[ 0 ] . parse :: < i32 > ( ) . unwrap ( ) ;
111+ let sub_dir_name = item_info[ 1 ] ;
112+ let mut path_clone = path. clone ( ) ;
113+ path_clone. push ( sub_dir_name) ;
114+ dir_dirs. push ( path_clone) ;
115+ } else if let Some ( file_size) = item_info[ 0 ] . parse :: < usize > ( ) . ok ( ) {
102116 let file_name = item_info[ 1 ] ;
103- let new_file = File { size : file_size, name : file_name. to_string ( ) } ;
104- //dirs.get_mut(current_dir_name).unwrap().add_file(new_file );
117+ let file = File { size : file_size, name : file_name. to_string ( ) } ;
118+ dir_files . push ( file ) ;
105119 }
106120 }
121+
122+ dirs. insert ( path. clone ( ) , dir_dirs) ;
123+ files. insert ( path. clone ( ) , dir_files) ;
107124 } ,
108125 _ => { /* Do nothing if command is not recognized */ }
109126 } ;
110127 }
128+ part1 ( dirs, files, vec ! [ "/" ] ) ;
111129}
0 commit comments