Skip to content

Instantly share code, notes, and snippets.

@vrnvu

vrnvu/day7.rs Secret

Last active December 7, 2022 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vrnvu/ca5c34fee059a62da4aab501ca230f1e to your computer and use it in GitHub Desktop.
Save vrnvu/ca5c34fee059a62da4aab501ca230f1e to your computer and use it in GitHub Desktop.
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(())
}
@vrnvu
Copy link
Author

vrnvu commented Dec 7, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment