Advent of Rust // Day 7
I spent this morning trying to build a super generic directory tree structure using dynamic types and ended up being frustrated because I don’t get how ownership, lifetime, and all that jazz works in Rust. So I went to work and after eight hours of that I just slammed out the dumbest solution I could think of… and it worked right away.
In short, I just keep track of directories and their sizes. Each file from the input is added to the current directory and all parent directories. Everything is stored in a flat hash map. The rest is simple filtering. I’m not proud of it, but it works.
fn directory_sizes(input: &str) -> HashMap<String, u32> {
let mut tree: HashMap<String, u32> = HashMap::new();
let directory_regex = Regex::new(r"^\$ cd (.+)$").unwrap();
let file_regex = Regex::new(r"^(\d+) (.+)$").unwrap();
let mut path = vec![String::from(".")];
for line in input.lines() {
for directory in directory_regex.captures(line) {
match &directory[1] {
"/" => path.truncate(1),
".." => { path.pop(); }
_ => path.push(String::from(&directory[1]))
};
}
for file in file_regex.captures(line) {
let file_size = file[1].parse::<u32>().unwrap();
for p in all_directories(&path) {
let new_size = tree.get(&p).unwrap_or(&0) + file_size;
tree.insert(p, new_size);
}
}
}
return tree;
}
fn all_directories(path: &Vec<String>) -> Vec<String> {
return (0..path.len()).map(|i| path[0..i + 1].join("/")).collect();
}
fn part_one(input: &str) -> u32 {
return directory_sizes(input).values().filter(|v| *v < &100000).sum();
}
fn part_two(input: &str) -> u32 {
let sizes = directory_sizes(input);
let total = 70000000;
let required = 30000000;
let unused = total - sizes.get(".").unwrap();
let missing = required - unused;
return *sizes.values().filter(|v| *v >= &missing).min().unwrap();
}
The full source and solutions for the others puzzles of Advent of Code can be found in my GitHub repository.
Comments
You can leave a comment by replying to this post on Mastodon.