Day 7. Wow that was not great
This commit is contained in:
parent
80c3a46ef1
commit
cf3867f355
5 changed files with 1109 additions and 0 deletions
115
day7/src/main.rs
Normal file
115
day7/src/main.rs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct File {
|
||||
name: String,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Directory {
|
||||
name: String,
|
||||
files: Vec<File>,
|
||||
directories: Vec<Rc<RefCell<Directory>>>,
|
||||
parent: Option<Rc<RefCell<Directory>>>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let contents = std::fs::read_to_string("data.txt").expect("Failed to read file");
|
||||
let lines: Vec<&str> = contents.lines().collect();
|
||||
let root = parse(&lines);
|
||||
|
||||
let mut sizes: HashMap<String, usize> = HashMap::new();
|
||||
set_sizes(root, &mut sizes);
|
||||
|
||||
// Part 1
|
||||
let sum = sizes
|
||||
.to_owned()
|
||||
.into_values()
|
||||
.filter(|&x| x <= 100000usize)
|
||||
.sum::<usize>();
|
||||
println!("Sum: {:?}", sum);
|
||||
|
||||
// Part 2
|
||||
let total = 70000000;
|
||||
let needed = 30000000;
|
||||
let used = sizes.get("").unwrap();
|
||||
let unused = total - used;
|
||||
let target = needed - unused;
|
||||
let delete = sizes
|
||||
.values()
|
||||
.fold(total, |acc, &x| if x < acc && x > target { x } else { acc });
|
||||
println!("Delete: {:?}", delete);
|
||||
}
|
||||
|
||||
fn parse(lines: &Vec<&str>) -> Rc<RefCell<Directory>> {
|
||||
let root = Rc::new(RefCell::new(Directory {
|
||||
name: String::from("/"),
|
||||
files: Vec::new(),
|
||||
directories: Vec::new(),
|
||||
parent: None,
|
||||
}));
|
||||
|
||||
let mut dir = Rc::clone(&root);
|
||||
|
||||
for line in lines.get(1..lines.len()).unwrap() {
|
||||
let parts = line.split(" ").collect::<Vec<&str>>();
|
||||
|
||||
match parts.as_slice() {
|
||||
["$", "ls"] => (), // ignore. we'll match on dirs and files below
|
||||
["dir", _] => (), // ignore. we'll add it when we cd into it
|
||||
[size, name] => {
|
||||
dir.borrow_mut().files.push(File {
|
||||
name: String::from(*name),
|
||||
size: size.parse().unwrap(),
|
||||
});
|
||||
}
|
||||
["$", "cd", ".."] => {
|
||||
// go up a directory by setting dir to the parent
|
||||
let temp = Rc::clone(&dir);
|
||||
dir = Rc::clone(temp.borrow().parent.as_ref().unwrap());
|
||||
}
|
||||
["$", "cd", path] => {
|
||||
// go down a directory by creating one and pointing dir at it
|
||||
let new_dir = Rc::new(RefCell::new(Directory {
|
||||
name: String::from(*path),
|
||||
files: Vec::new(),
|
||||
directories: Vec::new(),
|
||||
parent: Some(Rc::clone(&dir)),
|
||||
}));
|
||||
let temp = Rc::clone(&new_dir);
|
||||
dir.borrow_mut().directories.push(temp);
|
||||
dir = new_dir;
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
fn get_path(dir: Rc<RefCell<Directory>>) -> String {
|
||||
match &dir.borrow().parent {
|
||||
Some(d) => dir.borrow().name.to_string() + "/" + &get_path(d.to_owned()),
|
||||
None => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_sizes(dir: Rc<RefCell<Directory>>, hash: &mut HashMap<String, usize>) -> usize {
|
||||
let d = dir.borrow();
|
||||
let mut size = 0;
|
||||
|
||||
// add all the file sizes to this dir's size
|
||||
d.files.iter().for_each(|file| size += file.size);
|
||||
|
||||
// add all the sub dirs' size to this dir's size
|
||||
d.directories
|
||||
.iter()
|
||||
.for_each(|child| size += set_sizes(Rc::clone(child), hash));
|
||||
|
||||
let path = get_path(dir.to_owned());
|
||||
hash.insert(path, size);
|
||||
size
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue