refactor day 7 to be more iterator-y
This commit is contained in:
72
src/day07.rs
72
src/day07.rs
@@ -11,7 +11,7 @@ pub fn process_part_1(input: &str) -> u32 {
|
||||
let (_, commands) = parse_commands(input).unwrap();
|
||||
let directories = build_directory_tree_from_commands(commands);
|
||||
|
||||
directories.values().filter(|size| **size <= 100_000).sum()
|
||||
directories.values().filter(|&size| *size <= 100_000).sum()
|
||||
}
|
||||
|
||||
pub fn process_part_2(input: &str) -> u32 {
|
||||
@@ -25,44 +25,48 @@ pub fn process_part_2(input: &str) -> u32 {
|
||||
|
||||
directories
|
||||
.values()
|
||||
.filter(|size| **size >= wanted_space)
|
||||
.map(|size| *size)
|
||||
.filter(|&size| *size >= wanted_space)
|
||||
.map(|&size| size)
|
||||
.min()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn build_directory_tree_from_commands(commands: Vec<Command>) -> BTreeMap<String, u32> {
|
||||
let mut cwd: Vec<&str> = vec![];
|
||||
let mut directories: BTreeMap<String, u32> = BTreeMap::new();
|
||||
for command in commands {
|
||||
match command {
|
||||
Command::Cd("/") => {
|
||||
cwd = vec![];
|
||||
}
|
||||
Command::Cd("..") => {
|
||||
cwd.pop();
|
||||
}
|
||||
Command::Cd(name) => {
|
||||
cwd.push(name);
|
||||
}
|
||||
Command::Ls(files) => {
|
||||
for file in files {
|
||||
match file {
|
||||
DirEntry::File { name: _name, size } => {
|
||||
for i in 0..=cwd.len() {
|
||||
directories
|
||||
.entry(cwd[..i].join("/"))
|
||||
.and_modify(|f| *f += size)
|
||||
.or_insert(size);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
commands
|
||||
.iter()
|
||||
.fold((vec![], BTreeMap::new()), |(mut cwd, mut dirs), command| {
|
||||
match command {
|
||||
Command::Cd("/") => {
|
||||
cwd = vec![];
|
||||
}
|
||||
Command::Cd("..") => {
|
||||
cwd.pop();
|
||||
}
|
||||
Command::Cd(dir) => {
|
||||
cwd.push(*dir);
|
||||
}
|
||||
Command::Ls(files) => {
|
||||
// We don't actually care about individual files, just sum the files together
|
||||
// so we aren't looking up the BTreeMap as often
|
||||
let total_size = files
|
||||
.iter()
|
||||
.filter_map(|e| match e {
|
||||
DirEntry::File { size, .. } => Some(size),
|
||||
_ => None,
|
||||
})
|
||||
.sum();
|
||||
|
||||
for i in 0..=cwd.len() {
|
||||
dirs.entry(cwd[..i].join("/"))
|
||||
.and_modify(|f| *f += total_size)
|
||||
.or_insert(total_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
directories
|
||||
|
||||
(cwd, dirs)
|
||||
})
|
||||
.1
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -74,7 +78,11 @@ enum Command<'a> {
|
||||
#[derive(Debug)]
|
||||
enum DirEntry<'a> {
|
||||
Dir(&'a str),
|
||||
File { name: &'a str, size: u32 },
|
||||
#[allow(dead_code)]
|
||||
File {
|
||||
name: &'a str,
|
||||
size: u32,
|
||||
},
|
||||
}
|
||||
|
||||
fn parse_commands(input: &str) -> IResult<&str, Vec<Command>> {
|
||||
|
||||
Reference in New Issue
Block a user