Added day 7

This commit is contained in:
Sebastian 2022-12-13 12:15:36 +01:00
parent 16a9a199f8
commit ab84537ca5
2 changed files with 1194 additions and 0 deletions

1046
inputs/day7.txt Normal file

File diff suppressed because it is too large Load Diff

148
src/bin/day7.rs Normal file
View File

@ -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(&current_path) {
directories.insert(current_path.clone(), Directory::new());
}
} else if let Some(result) = dir_re.captures(&line) {
directories
.get_mut(&current_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(&current_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(())
}