-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
119 lines (104 loc) · 3.67 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use std::collections::HashMap;
use regex::Regex;
use regex::RegexSet;
struct Cwd {
dir: Vec<String>,
sizes: HashMap<String, usize>,
}
fn dir_to_string(dir: Vec<String>) -> String {
let mut dir_str = "/".to_string();
dir_str.push_str(dir.join("/").as_str());
return dir_str.to_string();
}
impl Cwd {
fn up(&mut self) {
//println!("----> in up()");
// remove last element from self.dir
self.dir.pop(); // last one is empty string
//println!("----> new directory: {}", self.to_string());
}
fn cd(&mut self, to_dir: String) {
//println!("----> in cd()");
self.dir.push(to_dir);
//println!("----> new directory: {}", self.to_string());
// add to_dir to the end of self.dir
}
fn to_string(&self) -> String {
return dir_to_string(self.dir.to_vec());
}
fn add_bytes(&mut self, bytes: usize) {
let mut dir = self.dir.to_vec();
loop {
let dir_string = dir_to_string(dir.to_vec());
*self.sizes.entry(dir_string.to_string()).or_insert(0) += bytes;
println!("Adding {} to {:?} ({})", bytes, dir, self.sizes.get(&dir_string).unwrap());
if let None = dir.pop() {
break;
}
}
}
}
fn main() {
// File hosts must exist in current path before this produces output
if let Ok(lines) = read_lines("./7.input") {
// Consumes the iterator, returns an (Optional) String
let mut cwd = Cwd {
dir: vec![],
sizes: HashMap::new(),
};
let set = RegexSet::new(&[
r"^\$ cd /$",
r"^\$ cd \.\.$",
r"^\$ cd ([a-z]*)$",
r"^\$ ls$",
r"^dir (.*)$",
r"^(\d+) (.*)$",
]).unwrap();
for line in lines {
if let Ok(line_str) = line {
let matches:Vec<_> = set.matches(&line_str).into_iter().collect();
println!("{line_str}");
match matches[0] {
0 => (), //println!("--> cd /"),
1 => cwd.up(),
2 => cwd.cd(Regex::new(r"^\$ cd ([a-z]*)$").unwrap().captures(&line_str).unwrap().get(1).unwrap().as_str().to_string()),
3 => (), //println!("--> ls"),
4 => (), //println!("--> a directory"),
5 => cwd.add_bytes(Regex::new(r"^(\d+) (.*)$")
.unwrap()
.captures(&line_str)
.unwrap()
.get(1)
.unwrap()
.as_str()
.to_string()
.parse::<usize>()
.unwrap()),
_ => println!("--> SOMETHING ELSE"),
}
}
}
println!("Total: {}", cwd.sizes.get("/").unwrap());
let free = 70000000 - cwd.sizes.get("/").unwrap();
let needed = 30000000 - free;
println!("Needed: {needed}");
let mut big_enough: Vec<usize> = Vec::new();
for (dir, size) in cwd.sizes.iter() {
if size >= &needed {
big_enough.push(*size);
}
}
big_enough.sort();
println!("{}", big_enough[0]);
}
}
// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}