Add 2022/07/01

This commit is contained in:
kageru 2022-12-07 11:07:07 +01:00
parent b519084a16
commit a52030278e
2 changed files with 1149 additions and 0 deletions

1014
2022/inputs/day07 Normal file

File diff suppressed because it is too large Load Diff

135
2022/src/bin/day07.rs Normal file
View File

@ -0,0 +1,135 @@
#![feature(test)]
extern crate test;
use std::ops::{Index, IndexMut};
use aoc2022::{boilerplate, common::*};
const DAY: usize = 7;
enum Node<'a> {
File(&'a str, usize),
Dir(&'a str, Vec<Box<Node<'a>>>),
}
impl<'a> IndexMut<&str> for Node<'a> {
fn index_mut(&mut self, index: &str) -> &mut Node<'a> {
match self {
Self::Dir(_, contents) => {
contents.iter_mut().find(|d| matches!(***d, Self::Dir ( name,_) if name == index)).expect("File not found")
}
Self::File(name, _) => panic!("Can’t index into a file ({name})"),
}
}
}
impl<'a> Index<&str> for Node<'a> {
type Output = Self;
fn index(&self, index: &str) -> &Self::Output {
match self {
Self::Dir(_, contents) => {
contents.iter().find(|&d| matches!(**d, Self::Dir ( name,_) if name == index)).expect("File not found")
}
Self::File(name, _) => panic!("Can’t index into a file ({name})"),
}
}
}
fn parse_input(raw: &str) -> Node<'_> {
let mut pwd = Vec::<&str>::new();
let mut fs = Node::Dir("/", Vec::new());
for cmd in raw.trim_start_matches("$ cd /\n$ ").split("$ ") {
// println!("Now at: {cmd}");
let mut lines = cmd.lines();
match lines.next().and_then(|s| s.split_once(' ')) {
Some(("cd", "..")) => {
pwd.pop();
}
Some(("cd", dir)) => pwd.push(dir),
// ls
_ => {
let mut cd = &mut fs;
for p in pwd.iter() {
cd = &mut cd[p];
}
match cd {
Node::Dir(_, contents) => {
for line in lines {
match line.split_once(' ') {
Some(("dir", d)) => contents.push(Box::new(Node::Dir(d, Vec::new()))),
Some((size, name)) => contents.push(Box::new(Node::File(name, size.parse().unwrap()))),
_ => unreachable!("Invalid directory contents: {line}"),
}
}
}
Node::File(_, _) => unreachable!("Can’t `ls` file contents"),
}
}
};
}
fs
}
fn part1(parsed: &Node<'_>) -> usize {
let mut n = 0;
node_size(parsed, &mut n);
n
}
fn node_size(node: &Node<'_>, n: &mut usize) -> usize {
match node {
Node::File(_, s) => *s,
Node::Dir(_, c) => {
let dir_size = c.iter().map(|d| node_size(d, n)).sum();
if dir_size <= 100_000 {
*n += dir_size;
}
dir_size
}
}
}
fn part2(parsed: &Node<'_>) -> usize {
unimplemented!()
}
boilerplate! {
TEST_INPUT == "$ 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",
tests: {
part1: { TEST_INPUT => 95437 },
part2: { TEST_INPUT => 24933642 },
},
bench1 == 1667443,
bench2 == 0,
bench_parse: node_name => "/",
}
#[cfg(test)]
fn node_name<'a>(n: &Node<'a>) -> &'a str {
match n {
Node::Dir(name, _) => name,
Node::File(name, _) => name,
}
}