84 lines
2.5 KiB
Rust
84 lines
2.5 KiB
Rust
use std::borrow::BorrowMut;
|
|
|
|
use petgraph::dot::*;
|
|
use petgraph::prelude::*;
|
|
use petgraph::*;
|
|
|
|
fn do_weights(g: &mut Graph<(String, u64), ()>, root_dir: NodeIndex<u32>) {
|
|
for edge in g.clone().edges_directed(root_dir, Outgoing) {
|
|
let mut target_weight = g.node_weight(edge.target()).unwrap();
|
|
if target_weight.1 == 0 {
|
|
do_weights(g, edge.target());
|
|
target_weight = g.node_weight(edge.target()).unwrap();
|
|
}
|
|
g.node_weight_mut(root_dir).unwrap().1 += target_weight.1;
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
const INPUT: &str = include_str!("../input.txt");
|
|
|
|
let mut g = DiGraph::<(String, u64), (), u32>::new();
|
|
|
|
let invalid_index: NodeIndex<u32> = NodeIndex::from(u32::MAX);
|
|
let mut curr_dir: NodeIndex<u32> = invalid_index;
|
|
let mut root_dir: NodeIndex<u32> = invalid_index;
|
|
|
|
for line in INPUT.lines() {
|
|
if line.starts_with("$ cd") {
|
|
let new_dir = &line[5..];
|
|
|
|
if new_dir == ".." {
|
|
curr_dir = g
|
|
.edges_directed(curr_dir, Incoming)
|
|
.next()
|
|
.unwrap()
|
|
.source();
|
|
} else {
|
|
let prev_dir = curr_dir;
|
|
curr_dir = g.add_node((new_dir.to_string() + "/", 0));
|
|
if prev_dir == invalid_index {
|
|
root_dir = curr_dir;
|
|
} else {
|
|
g.add_edge(prev_dir, curr_dir, ());
|
|
}
|
|
}
|
|
} else if line.starts_with("$ ls") {
|
|
continue;
|
|
} else {
|
|
let (size, name) = line.split_once(' ').unwrap();
|
|
if size == "dir" {
|
|
continue;
|
|
}
|
|
|
|
let size: u64 = size.parse().unwrap();
|
|
|
|
let n = g.add_node((name.to_string(), size));
|
|
g.add_edge(curr_dir, n, ());
|
|
}
|
|
}
|
|
|
|
do_weights(g.borrow_mut(), root_dir);
|
|
|
|
println!("{:?}\n\n", Dot::with_config(&g, &[Config::EdgeNoLabel]));
|
|
|
|
let total = g
|
|
.node_weights()
|
|
.filter(|(n, w)| n.ends_with("/") && *w <= 100000)
|
|
.map(|(_, w)| w)
|
|
.sum::<u64>();
|
|
println!("total: {total}");
|
|
|
|
let used_space = g.node_weight(root_dir).unwrap().1;
|
|
let free_space = 70000000 - used_space;
|
|
let need_to_free = 30000000 - free_space;
|
|
|
|
let delete = g
|
|
.node_weights()
|
|
.filter(|(n, w)| n.ends_with("/") && *w > need_to_free)
|
|
.map(|(_, w)| w)
|
|
.min()
|
|
.unwrap();
|
|
println!("delete size: {delete}");
|
|
}
|