Added day 7
This commit is contained in:
parent
16a9a199f8
commit
ab84537ca5
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,148 @@
|
||||||
|
use regex::Regex;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Directory {
|
||||||
|
subdirs: HashSet<String>,
|
||||||
|
files: HashMap<String, u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Directory {
|
||||||
|
fn new() -> Directory {
|
||||||
|
Directory {
|
||||||
|
subdirs: HashSet::new(),
|
||||||
|
files: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_file(&mut self, name: &str, size: u32) {
|
||||||
|
self.files.insert(name.to_owned(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_subdir(&mut self, name: &str) {
|
||||||
|
self.subdirs.insert(name.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_file_sizes(&self) -> u32 {
|
||||||
|
self.files.values().fold(0, |a, b| a + b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_directory_size(path: &Vec<String>, directories: &HashMap<Vec<String>, Directory>) -> u32 {
|
||||||
|
let mut result = directories[path].get_file_sizes();
|
||||||
|
|
||||||
|
for subdir in directories[path].subdirs.iter() {
|
||||||
|
let mut sub_path = path.clone();
|
||||||
|
sub_path.push(subdir.to_owned());
|
||||||
|
|
||||||
|
result += get_directory_size(&sub_path, directories);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sum_up_dirs(path: &Vec<String>, directories: &HashMap<Vec<String>, Directory>) -> u32 {
|
||||||
|
let mut result = 0;
|
||||||
|
let own_size = get_directory_size(path, directories);
|
||||||
|
if own_size < 100000 {
|
||||||
|
result += own_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for subdir in directories[path].subdirs.iter() {
|
||||||
|
let mut sub_path = path.clone();
|
||||||
|
sub_path.push(subdir.to_owned());
|
||||||
|
result += sum_up_dirs(&sub_path, directories);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_optimal_deletion(
|
||||||
|
path: &Vec<String>,
|
||||||
|
optimal_size: u32,
|
||||||
|
current_optimum: u32,
|
||||||
|
directories: &HashMap<Vec<String>, Directory>,
|
||||||
|
) -> u32 {
|
||||||
|
let own_size = get_directory_size(path, directories);
|
||||||
|
let mut result = if own_size >= optimal_size && own_size < current_optimum {
|
||||||
|
own_size
|
||||||
|
} else {
|
||||||
|
current_optimum
|
||||||
|
};
|
||||||
|
|
||||||
|
for subdir in directories[path].subdirs.iter() {
|
||||||
|
let mut sub_path = path.clone();
|
||||||
|
sub_path.push(subdir.to_owned());
|
||||||
|
result = find_optimal_deletion(&sub_path, optimal_size, result, directories);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let file = File::open("inputs/day7.txt")?;
|
||||||
|
let mut lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
|
||||||
|
|
||||||
|
let mut directories = HashMap::new();
|
||||||
|
let mut current_path: Vec<String> = Vec::new();
|
||||||
|
|
||||||
|
let cd_re = Regex::new(r"^\$ cd (.+)$").unwrap();
|
||||||
|
let dir_re = Regex::new(r"^dir (.+)$").unwrap();
|
||||||
|
let file_re = Regex::new(r"^([0-9]+) (.+)$").unwrap();
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
if let Some(result) = cd_re.captures(&line) {
|
||||||
|
let target = &result[1];
|
||||||
|
if target == "/" {
|
||||||
|
current_path = vec!["/".to_owned()];
|
||||||
|
} else if target == ".." {
|
||||||
|
current_path.pop().unwrap();
|
||||||
|
} else {
|
||||||
|
current_path.push(target.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !directories.contains_key(¤t_path) {
|
||||||
|
directories.insert(current_path.clone(), Directory::new());
|
||||||
|
}
|
||||||
|
} else if let Some(result) = dir_re.captures(&line) {
|
||||||
|
directories
|
||||||
|
.get_mut(¤t_path)
|
||||||
|
.unwrap()
|
||||||
|
.add_subdir(&result[1]);
|
||||||
|
let mut subdir_path = current_path.clone();
|
||||||
|
subdir_path.push(result[1].to_owned());
|
||||||
|
if !directories.contains_key(&subdir_path) {
|
||||||
|
directories.insert(subdir_path, Directory::new());
|
||||||
|
}
|
||||||
|
} else if let Some(result) = file_re.captures(&line) {
|
||||||
|
let size: u32 = result[1].parse().unwrap();
|
||||||
|
let name = &result[2];
|
||||||
|
|
||||||
|
directories
|
||||||
|
.get_mut(¤t_path)
|
||||||
|
.unwrap()
|
||||||
|
.add_file(name, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let answer1 = sum_up_dirs(&vec!["/".to_owned()], &directories);
|
||||||
|
|
||||||
|
println!("Answer Part1: {}", answer1);
|
||||||
|
|
||||||
|
let unused_space = 70000000 - get_directory_size(&vec!["/".to_owned()], &directories);
|
||||||
|
let minimum_deletion_size = 30000000 - unused_space;
|
||||||
|
|
||||||
|
let answer2 = find_optimal_deletion(
|
||||||
|
&vec!["/".to_owned()],
|
||||||
|
minimum_deletion_size,
|
||||||
|
30000000,
|
||||||
|
&directories,
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("Answer Part2: {}", answer2);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue