Alternative implementation that does not use unsafe or a tree structures (is slower however)

This commit is contained in:
Dreaded_X 2022-12-08 00:31:35 +01:00
parent d0bef9e654
commit 47907ef562
Signed by: Dreaded_X
GPG Key ID: 76BDEC4E165D8AD9

107
2022/src/bin/day7_alt.rs Normal file
View File

@ -0,0 +1,107 @@
#![feature(test)]
use std::{path::PathBuf, collections::HashMap, ops::AddAssign};
use anyhow::Result;
use aoc::Solver;
// -- Runners --
fn main() -> Result<()> {
Day::solve()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn part1_test1() -> Result<()> {
Day::test(aoc::Part::ONE, "test-1", 95437)
}
#[test]
fn part1_solution() -> Result<()> {
Day::test(aoc::Part::ONE, "input", 2031851)
}
#[test]
fn part2_test1() -> Result<()> {
Day::test(aoc::Part::TWO, "test-1", 24933642)
}
#[test]
fn part2_solution() -> Result<()> {
Day::test(aoc::Part::TWO, "input", 2568781)
}
// Benchmarks
extern crate test;
#[bench]
#[ignore]
fn part1_bench(b: &mut test::Bencher) {
Day::benchmark(aoc::Part::ONE, b)
}
#[bench]
#[ignore]
fn part2_bench(b: &mut test::Bencher) {
Day::benchmark(aoc::Part::TWO, b)
}
}
// -- Helper functions --
fn process(input: &str) -> Vec<u32> {
let mut path = PathBuf::new();
let mut map = HashMap::new();
input
.lines()
.map(|line| line.rsplit_once(" ").unwrap())
.for_each(|split| {
match split {
("$ cd", "/") => { path.clear(); }, // Clear the path
("$ cd", "..") => { path.pop(); }, // Go up one level in the path
("$ cd", name) => { path.push(name); }, // Enter a directory
("$", "ls") => {},
("dir", _name) => {},
(size, _name) => {
let mut temp = path.clone();
while {
// Update the size of the current and all parent directories
map.entry(temp.clone()).or_insert(0).add_assign(size.parse::<u32>().unwrap());
temp.pop()
} {}
},
}
});
map.iter().map(|(_, &size)| size).collect()
}
// -- Solution --
pub struct Day;
impl aoc::Solver for Day {
type Output = u32;
fn day() -> u8 {
7
}
fn part1(input: &str) -> Self::Output {
process(input)
.iter()
.filter(|&&size| size < 100000)
.sum()
}
fn part2(input: &str) -> Self::Output {
let mut sizes = process(input);
sizes.sort();
// The root is always the larges directory, so it will end up in the last element
let need_to_free = sizes.last().unwrap() - 40000000;
sizes.iter()
.find_map(|&size| {
if size > need_to_free {
Some(size)
} else {
None
}
}).unwrap()
}
}