parent
52dfdcc4bb
commit
1ca80ba6d2
@ -0,0 +1,7 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
version = 3 |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "d7" |
||||||
|
version = "0.1.0" |
@ -0,0 +1,8 @@ |
|||||||
|
[package] |
||||||
|
name = "d7" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||||
|
|
||||||
|
[dependencies] |
@ -0,0 +1,127 @@ |
|||||||
|
use std::{cell::RefCell, collections::HashMap, fs::read_to_string, io::Result, rc::Rc}; |
||||||
|
|
||||||
|
#[derive(Debug)] |
||||||
|
enum Entry { |
||||||
|
Dir(Option<RME>, HashMap<String, RME>), |
||||||
|
File(usize), |
||||||
|
} |
||||||
|
|
||||||
|
type RME = Rc<RefCell<Entry>>; |
||||||
|
|
||||||
|
impl Entry { |
||||||
|
pub fn new_dir<S: AsRef<str>>(parent: &Option<RME>, name: S) -> RME { |
||||||
|
let this = Rc::new(RefCell::new(Entry::Dir(parent.clone(), HashMap::new()))); |
||||||
|
let this_clone = this.clone(); |
||||||
|
match parent { |
||||||
|
Some(parent) => match &mut *parent.borrow_mut() { |
||||||
|
Entry::Dir(_, ref mut children) => { |
||||||
|
children.insert(name.as_ref().to_owned(), this_clone); |
||||||
|
} |
||||||
|
_ => panic!("Attaching a child to a file"), |
||||||
|
}, |
||||||
|
None => (), |
||||||
|
} |
||||||
|
|
||||||
|
this |
||||||
|
} |
||||||
|
|
||||||
|
pub fn new_file<S: AsRef<str>>(parent: RME, name: S, size: usize) -> RME { |
||||||
|
let this = Rc::new(RefCell::new(Entry::File(size))); |
||||||
|
let this_clone = this.clone(); |
||||||
|
match &mut *parent.borrow_mut() { |
||||||
|
Entry::Dir(_, ref mut children) => { |
||||||
|
children.insert(name.as_ref().to_owned(), this_clone); |
||||||
|
} |
||||||
|
_ => panic!("Attaching a child to a file"), |
||||||
|
} |
||||||
|
this |
||||||
|
} |
||||||
|
|
||||||
|
pub fn size(&self) -> usize { |
||||||
|
match self { |
||||||
|
Entry::File(size) => *size, |
||||||
|
Entry::Dir(_, ref children) => children.values().map(|f| f.borrow().size()).sum(), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn parent(&self) -> RME { |
||||||
|
match self { |
||||||
|
Entry::Dir(parent, _) => parent.as_ref().unwrap().clone(), |
||||||
|
_ => panic!("Get parent for file"), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn file<S: AsRef<str>>(&self, name: S) -> RME { |
||||||
|
match self { |
||||||
|
Entry::Dir(_, ref children) => children.get(name.as_ref()).unwrap().clone(), |
||||||
|
_ => panic!("Get file for file"), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn iter_dirs<F: FnMut(&Self)>(&self, f: &mut F) { |
||||||
|
match self { |
||||||
|
Entry::Dir(_, ref children) => { |
||||||
|
f(self); |
||||||
|
for child in children.values() { |
||||||
|
child.borrow().iter_dirs(f); |
||||||
|
} |
||||||
|
} |
||||||
|
_ => (), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn main() -> Result<()> { |
||||||
|
let none = None; |
||||||
|
let root = Entry::new_dir(&none, "/"); |
||||||
|
|
||||||
|
let mut current = root.clone(); |
||||||
|
|
||||||
|
for line in read_to_string("input.txt")? |
||||||
|
.split("\n") |
||||||
|
.filter(|x| !x.is_empty()) |
||||||
|
{ |
||||||
|
if line.starts_with("$ cd ") { |
||||||
|
let path = line.split_at(5).1; |
||||||
|
|
||||||
|
if path == "/" { |
||||||
|
current = root.clone(); |
||||||
|
} else if path == ".." { |
||||||
|
let next = current.borrow().parent(); |
||||||
|
current = next; |
||||||
|
} else { |
||||||
|
let next = current.borrow().file(path); |
||||||
|
current = next; |
||||||
|
} |
||||||
|
} else if line == "$ ls" { |
||||||
|
// ignore
|
||||||
|
} else if line.starts_with("dir ") { |
||||||
|
let path = line.split_at(4).1; |
||||||
|
Entry::new_dir(&Some(current.clone()), path); |
||||||
|
} else { |
||||||
|
let split = line.split(" ").collect::<Vec<_>>(); |
||||||
|
let size = split[0].parse::<usize>().unwrap(); |
||||||
|
let path = split[1]; |
||||||
|
Entry::new_file(current.clone(), path, size); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let mut sum_p1 = 0; |
||||||
|
let mut smallest_p2 = usize::MAX; |
||||||
|
|
||||||
|
let to_free = 30000000usize - (70000000usize - root.borrow().size()); |
||||||
|
root.borrow().iter_dirs(&mut |dir| { |
||||||
|
let size = dir.size(); |
||||||
|
if size <= 100000 { |
||||||
|
sum_p1 += size |
||||||
|
} |
||||||
|
if size >= to_free && size <= smallest_p2 { |
||||||
|
smallest_p2 = size |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
println!("Part 1: {}", sum_p1); |
||||||
|
println!("Part 2: {}", smallest_p2); |
||||||
|
|
||||||
|
Ok(()) |
||||||
|
} |
Loading…
Reference in new issue