[rs] Simplify 2022_07
This commit is contained in:
parent
5e74d92d43
commit
dd5cf6019d
1 changed files with 20 additions and 80 deletions
|
|
@ -1,15 +1,5 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
enum LsItem {
|
|
||||||
File(usize, String),
|
|
||||||
Dir(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Command {
|
|
||||||
Cd(String),
|
|
||||||
Ls(Vec<LsItem>),
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Fs {
|
enum Fs {
|
||||||
Dir(HashMap<String, Fs>),
|
Dir(HashMap<String, Fs>),
|
||||||
File(usize),
|
File(usize),
|
||||||
|
|
@ -24,11 +14,8 @@ impl Fs {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn at_path(&mut self, path: &[String]) -> &mut Self {
|
fn at_path(&mut self, path: &[String]) -> &mut Self {
|
||||||
let mut result = self;
|
path.iter()
|
||||||
for segment in path {
|
.fold(self, |p, s| p.as_dir().get_mut(s).unwrap())
|
||||||
result = result.as_dir().get_mut(segment).unwrap();
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
|
|
@ -50,66 +37,25 @@ impl Fs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_chunks(input: &str) -> Vec<(String, Vec<String>)> {
|
|
||||||
let mut lines = input.lines().peekable();
|
|
||||||
let mut chunks = vec![];
|
|
||||||
while let Some(command) = lines.next() {
|
|
||||||
assert!(command.starts_with("$ "));
|
|
||||||
let mut items = vec![];
|
|
||||||
while let Some(item) = lines.peek() {
|
|
||||||
if item.starts_with("$ ") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
items.push(item.to_string());
|
|
||||||
lines.next();
|
|
||||||
}
|
|
||||||
chunks.push((command.to_string(), items));
|
|
||||||
}
|
|
||||||
chunks
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn solve(input: String) {
|
pub fn solve(input: String) {
|
||||||
// Parse commands
|
// Parse commands and build fs tree
|
||||||
let commands = command_chunks(&input)
|
|
||||||
.into_iter()
|
|
||||||
.map(|(command, items)| {
|
|
||||||
if let Some(name) = command.strip_prefix("$ cd ") {
|
|
||||||
Command::Cd(name.to_string())
|
|
||||||
} else {
|
|
||||||
assert_eq!(command, "$ ls");
|
|
||||||
let ls_items = items
|
|
||||||
.into_iter()
|
|
||||||
.map(|item| {
|
|
||||||
let (left, name) = item.split_once(' ').unwrap();
|
|
||||||
if left == "dir" {
|
|
||||||
LsItem::Dir(name.to_string())
|
|
||||||
} else {
|
|
||||||
LsItem::File(left.parse::<usize>().unwrap(), name.to_string())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
Command::Ls(ls_items)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// Build fs tree
|
|
||||||
let mut fs = Fs::Dir(HashMap::new());
|
let mut fs = Fs::Dir(HashMap::new());
|
||||||
let mut path = vec![];
|
let mut path = vec![];
|
||||||
for command in commands {
|
for line in input.lines() {
|
||||||
match command {
|
if let Some(name) = line.strip_prefix("$ cd ") {
|
||||||
Command::Cd(to) if to == "/" => path = vec![],
|
match name {
|
||||||
Command::Cd(to) if to == ".." => _ = path.pop(), // Learned a new trick
|
"/" => path.clear(),
|
||||||
Command::Cd(to) => path.push(to),
|
".." => _ = path.pop(),
|
||||||
Command::Ls(items) => {
|
_ => path.push(name.to_string()),
|
||||||
for item in items {
|
|
||||||
let map = fs.at_path(&path).as_dir();
|
|
||||||
match item {
|
|
||||||
LsItem::File(size, name) => map.insert(name, Fs::File(size)),
|
|
||||||
LsItem::Dir(name) => map.insert(name, Fs::Dir(HashMap::new())),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if line == "$ ls" {
|
||||||
|
} else if let Some(name) = line.strip_prefix("dir ") {
|
||||||
|
let dir = Fs::Dir(HashMap::new());
|
||||||
|
fs.at_path(&path).as_dir().insert(name.to_string(), dir);
|
||||||
|
} else {
|
||||||
|
let (size, name) = line.split_once(' ').unwrap();
|
||||||
|
let file = Fs::File(size.parse().unwrap());
|
||||||
|
fs.at_path(&path).as_dir().insert(name.to_string(), file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,14 +64,8 @@ pub fn solve(input: String) {
|
||||||
let part1 = dir_sizes.iter().filter(|s| **s <= 100000).sum::<usize>();
|
let part1 = dir_sizes.iter().filter(|s| **s <= 100000).sum::<usize>();
|
||||||
println!("Part 1: {part1}");
|
println!("Part 1: {part1}");
|
||||||
|
|
||||||
let total_available = 70000000;
|
// 70000000 available, 30000000 required for update: We can't go over 40000000.
|
||||||
let required_for_update = 30000000;
|
let min = fs.size() - 40000000;
|
||||||
let unused = total_available - fs.size();
|
let part2 = dir_sizes.into_iter().filter(|s| *s >= min).min().unwrap();
|
||||||
let free_at_least = required_for_update - unused;
|
|
||||||
let part2 = dir_sizes
|
|
||||||
.into_iter()
|
|
||||||
.filter(|s| *s >= free_at_least)
|
|
||||||
.min()
|
|
||||||
.unwrap();
|
|
||||||
println!("Part 2: {part2}");
|
println!("Part 2: {part2}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue