-
-
Save vrnvu/ca5c34fee059a62da4aab501ca230f1e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
cell::RefCell, | |
collections::HashMap, | |
io::{BufRead, BufReader}, | |
num::ParseIntError, | |
str::FromStr, | |
}; | |
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; | |
#[derive(Debug, Clone)] | |
enum Type { | |
Root, | |
Dir, | |
File, | |
} | |
#[derive(Debug, Clone)] | |
enum Input { | |
CD { to: String }, | |
CDROOT, | |
CDBACK, | |
LS, | |
FILE { size: u64, name: String }, | |
DIR { name: String }, | |
} | |
impl FromStr for Input { | |
type Err = ParseIntError; | |
fn from_str(line: &str) -> std::result::Result<Self, Self::Err> { | |
let line: Vec<&str> = line.split(" ").collect(); | |
if line[0] == "$" { | |
if line[1] == "cd" { | |
if line[2] == "/" { | |
Ok(Input::CDROOT) | |
} else if line[2] == ".." { | |
Ok(Input::CDBACK) | |
} else { | |
Ok(Input::CD { | |
to: line[2].to_string(), | |
}) | |
} | |
} else { | |
Ok(Input::LS) | |
} | |
} else { | |
if line[0] == "dir" { | |
Ok(Input::DIR { | |
name: line[1].to_string(), | |
}) | |
} else { | |
Ok(Input::FILE { | |
size: line[0].parse()?, | |
name: line[1].to_string(), | |
}) | |
} | |
} | |
} | |
} | |
#[derive(Debug, Clone)] | |
struct Dir { | |
name: String, | |
is_type: Type, | |
size: u64, | |
parent: Option<String>, | |
subdirs: Vec<String>, | |
} | |
impl Dir { | |
fn new_file(size: u64, name: String, parent: String) -> Dir { | |
Dir { | |
name: Dir::format_name(&parent, &name), | |
is_type: Type::File, | |
size, | |
parent: Some(parent), | |
subdirs: Vec::new(), | |
} | |
} | |
fn new_dir(name: String, parent: String) -> Dir { | |
Dir { | |
name: Dir::format_name(&parent, &name), | |
is_type: Type::Dir, | |
size: 0, | |
parent: Some(parent), | |
subdirs: Vec::new(), | |
} | |
} | |
fn format_name(parent: &String, name: &String) -> String { | |
format!("{}{}/", parent, name) | |
} | |
} | |
struct Filesystem { | |
current_dir: Dir, | |
fs: HashMap<String, RefCell<Dir>>, | |
} | |
impl Filesystem { | |
fn new() -> Filesystem { | |
let mut fs: HashMap<String, RefCell<Dir>> = HashMap::new(); | |
let root: Dir = Dir { | |
name: String::from("/"), | |
is_type: Type::Root, | |
size: 0, | |
parent: None, | |
subdirs: Vec::new(), | |
}; | |
fs.insert(root.name.to_owned(), RefCell::new(root.to_owned())); | |
Filesystem { | |
current_dir: root, | |
fs, | |
} | |
} | |
fn cd(self: &mut Self, to: String) { | |
let name = Dir::format_name(&self.current_dir.name, &to); | |
if let Some(dir) = self.fs.get_mut(&name) { | |
self.current_dir = dir.borrow_mut().to_owned(); | |
} | |
} | |
fn cd_root(self: &mut Self) { | |
if let Some(dir) = self.fs.get_mut("/") { | |
self.current_dir = dir.borrow_mut().to_owned(); | |
} | |
} | |
fn cd_back(self: &mut Self) { | |
let parent_name = self.current_dir.parent.to_owned().unwrap(); | |
if let Some(dir) = self.fs.get_mut(&parent_name) { | |
self.current_dir = dir.borrow_mut().to_owned(); | |
} | |
} | |
fn insert_file(self: &mut Self, size: u64, name: String) { | |
let file = Dir::new_file(size, name, self.current_dir.name.to_owned()); | |
self.fs | |
.insert(file.name.to_owned(), RefCell::new(file.to_owned())); | |
self.current_dir.subdirs.push(file.name.to_owned()); | |
self.fs.insert( | |
self.current_dir.name.to_owned(), | |
RefCell::new(self.current_dir.to_owned()), | |
); | |
} | |
fn insert_dir(self: &mut Self, name: String) { | |
let dir = Dir::new_dir(name, self.current_dir.name.to_owned()); | |
self.fs | |
.insert(dir.name.to_owned(), RefCell::new(dir.to_owned())); | |
self.current_dir.subdirs.push(dir.name.to_owned()); | |
self.fs.insert( | |
self.current_dir.name.to_owned(), | |
RefCell::new(self.current_dir.to_owned()), | |
); | |
} | |
fn index(self: &mut Self) { | |
for value in self.fs.values() { | |
let mut value = value.borrow_mut(); | |
let file_size = value.size; | |
match value.is_type { | |
Type::Root => continue, | |
Type::Dir => continue, | |
Type::File => { | |
while let Some(parent_name) = value.parent.to_owned() { | |
let mut parent = self.fs.get(parent_name.as_str()).unwrap().borrow_mut(); | |
parent.size += file_size; | |
value = parent; | |
} | |
} | |
} | |
} | |
} | |
} | |
fn one(mut fs: HashMap<String, RefCell<Dir>>) { | |
fs.retain(|_, v| match v.borrow().is_type { | |
Type::Root => true, | |
Type::Dir => true, | |
Type::File => false, | |
}); | |
fs.retain(|_, v| v.borrow().size <= 100_000); | |
let r = fs | |
.values() | |
.into_iter() | |
.map(|v| v.borrow().size) | |
.sum::<u64>(); | |
println!("one: {}", r); | |
} | |
fn two(mut fs: HashMap<String, RefCell<Dir>>) { | |
fs.retain(|_, v| match v.borrow().is_type { | |
Type::Root => true, | |
Type::Dir => true, | |
Type::File => false, | |
}); | |
let mut dirs: Vec<u64> = fs | |
.values() | |
.into_iter() | |
.map(|v| v.borrow().size) | |
.collect::<Vec<u64>>(); | |
dirs.sort(); | |
let disk_space = 70_000_000; | |
let need_space = 30_000_000; | |
let used_space = dirs.last().unwrap(); | |
let unused_space = disk_space - used_space; | |
let threshold = need_space - unused_space; | |
for d in dirs.iter() { | |
if d >= &threshold { | |
println!("two: {:#?}", d); | |
break; | |
} | |
} | |
} | |
fn main() -> Result<()> { | |
let filepath = "./inputs/7.txt"; | |
let file = std::fs::File::open(filepath)?; | |
let reader = BufReader::new(file); | |
let mut filesystem = Filesystem::new(); | |
for line in reader.lines() { | |
let input = line?.parse()?; | |
match input { | |
Input::CD { to } => filesystem.cd(to), | |
Input::CDROOT => filesystem.cd_root(), | |
Input::CDBACK => filesystem.cd_back(), | |
Input::LS => continue, | |
Input::FILE { size, name } => filesystem.insert_file(size, name), | |
Input::DIR { name } => filesystem.insert_dir(name), | |
} | |
} | |
filesystem.index(); | |
one(filesystem.fs.clone()); | |
two(filesystem.fs.clone()); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
HAHAHAHA
Este a;o no hay ni rust ni haskells ni nada raro?
Bueno mejor eso que no dejarlo al 5 dia porque no entiendes una monad
HAHAHAHA