2022-7...
This commit is contained in:
parent
61268dc5ec
commit
93d7537f66
1 changed files with 169 additions and 0 deletions
169
src/bin/2022-7.rs
Normal file
169
src/bin/2022-7.rs
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
use eyes::parse;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::{cell::RefCell, collections::HashMap, iter, rc::Rc};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let input = aoc::input!();
|
||||||
|
println!("part 1: {}", part1(&input));
|
||||||
|
println!("part 1: {}", part2(&input));
|
||||||
|
}
|
||||||
|
|
||||||
|
type RefNode = Rc<RefCell<Node>>;
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Node {
|
||||||
|
size: u64,
|
||||||
|
children: HashMap<String, RefNode>,
|
||||||
|
parent: Option<RefNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node {
|
||||||
|
fn total_size(&self) -> u64 {
|
||||||
|
self.children
|
||||||
|
.values()
|
||||||
|
.map(|child| child.borrow().total_size())
|
||||||
|
.sum::<u64>()
|
||||||
|
+ self.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_dirs(n: RefNode) -> Box<dyn Iterator<Item = RefNode>> {
|
||||||
|
let children = n.borrow().children.values().cloned().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Box::new(
|
||||||
|
iter::once(n).chain(
|
||||||
|
children
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|c| {
|
||||||
|
if c.borrow().size == 0 {
|
||||||
|
Some(all_dirs(c))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flatten(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> u64 {
|
||||||
|
let root = RefNode::default();
|
||||||
|
let mut node = root.clone();
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
match line {
|
||||||
|
l if l.starts_with("$ cd") => {
|
||||||
|
let dir = parse!(l, "$ cd {}", String);
|
||||||
|
match dir.as_str() {
|
||||||
|
"/" => continue,
|
||||||
|
".." => {
|
||||||
|
let parent = node.borrow().parent.clone().unwrap();
|
||||||
|
node = parent;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let child = node.borrow_mut().children.entry(dir).or_default().clone();
|
||||||
|
node = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // cd
|
||||||
|
l if l.starts_with("$ ls") => continue, // ls
|
||||||
|
l if l.starts_with("dir ") => {
|
||||||
|
// dir entry
|
||||||
|
let dir = parse!(l, "dir {}", String);
|
||||||
|
let entry = node.borrow_mut().children.entry(dir).or_default().clone();
|
||||||
|
entry.borrow_mut().parent = Some(node.clone());
|
||||||
|
}
|
||||||
|
l => {
|
||||||
|
// file entry
|
||||||
|
let (size, file) = parse!(l, "{} {}", u64, String);
|
||||||
|
let entry = node.borrow_mut().children.entry(file).or_default().clone();
|
||||||
|
entry.borrow_mut().size = size;
|
||||||
|
entry.borrow_mut().parent = Some(node.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
all_dirs(root)
|
||||||
|
.map(|d| d.borrow().total_size())
|
||||||
|
.filter(|&s| s <= 100_000)
|
||||||
|
.sum::<u64>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> u64 {
|
||||||
|
let root = RefNode::default();
|
||||||
|
let mut node = root.clone();
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
match line {
|
||||||
|
l if l.starts_with("$ cd") => {
|
||||||
|
let dir = parse!(l, "$ cd {}", String);
|
||||||
|
match dir.as_str() {
|
||||||
|
"/" => continue,
|
||||||
|
".." => {
|
||||||
|
let parent = node.borrow().parent.clone().unwrap();
|
||||||
|
node = parent;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let child = node.borrow_mut().children.entry(dir).or_default().clone();
|
||||||
|
node = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // cd
|
||||||
|
l if l.starts_with("$ ls") => continue, // ls
|
||||||
|
l if l.starts_with("dir ") => {
|
||||||
|
// dir entry
|
||||||
|
let dir = parse!(l, "dir {}", String);
|
||||||
|
let entry = node.borrow_mut().children.entry(dir).or_default().clone();
|
||||||
|
entry.borrow_mut().parent = Some(node.clone());
|
||||||
|
}
|
||||||
|
l => {
|
||||||
|
// file entry
|
||||||
|
let (size, file) = parse!(l, "{} {}", u64, String);
|
||||||
|
let entry = node.borrow_mut().children.entry(file).or_default().clone();
|
||||||
|
entry.borrow_mut().size = size;
|
||||||
|
entry.borrow_mut().parent = Some(node.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let free_space = 70000000 - root.borrow().total_size();
|
||||||
|
all_dirs(root)
|
||||||
|
.map(|d| d.borrow().total_size())
|
||||||
|
.filter(|&s| s >= 30000000 - free_space)
|
||||||
|
.min()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples() {
|
||||||
|
let example = r#"$ cd /
|
||||||
|
$ ls
|
||||||
|
dir a
|
||||||
|
14848514 b.txt
|
||||||
|
8504156 c.dat
|
||||||
|
dir d
|
||||||
|
$ cd a
|
||||||
|
$ ls
|
||||||
|
dir e
|
||||||
|
29116 f
|
||||||
|
2557 g
|
||||||
|
62596 h.lst
|
||||||
|
$ cd e
|
||||||
|
$ ls
|
||||||
|
584 i
|
||||||
|
$ cd ..
|
||||||
|
$ cd ..
|
||||||
|
$ cd d
|
||||||
|
$ ls
|
||||||
|
4060174 j
|
||||||
|
8033020 d.log
|
||||||
|
5626152 d.ext
|
||||||
|
7214296 k"#;
|
||||||
|
|
||||||
|
assert_eq!(part1(example), 95437);
|
||||||
|
assert_eq!(part2(example), 24933642);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue