1
0
Fork 0

Solve day 7

This commit is contained in:
Lars Martens 2022-12-07 14:19:35 +01:00
parent 93ee369010
commit b97e512d98
3 changed files with 1203 additions and 0 deletions

1052
input/07 Normal file

File diff suppressed because it is too large Load diff

23
input/07-test Normal file
View file

@ -0,0 +1,23 @@
$ 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

128
src/bin/07.rs Normal file
View file

@ -0,0 +1,128 @@
use std::str::FromStr;
use aoc2022::*;
const INPUT: &str = include_str!("../../input/07");
fn main() {
let tree = Tree::from_input();
solved_level_1(tree.part1());
solved_level_2(tree.part2());
}
#[derive(Debug)]
struct Tree(Vec<Node>);
impl Tree {
fn from_input() -> Self {
let mut tree = vec![Node::directory(0)];
let mut current = 0;
// Skip 1 skips the initial "cd /".
let input = INPUT.lines().filter_map(|l| l.parse::<Line>().ok()).skip(1);
for line in input {
match line {
Line::CommandUp => current = tree[current].parent(),
Line::CommandInto => {
let handle = tree.len();
tree.push(Node::directory(current));
tree[current].add_child(handle);
current = handle;
}
Line::File(size) => {
let handle = tree.len();
tree.push(Node::file(current, size));
tree[current].add_child(handle);
}
}
}
Self(tree)
}
fn dir_sizes(&self) -> impl Iterator<Item = usize> + '_ {
self.0
.iter()
.enumerate()
.filter_map(|(i, node)| match node {
Node::Directory { .. } => Some(i),
Node::File { .. } => None,
})
.map(|i| self.sum_size(i))
}
fn part1(&self) -> usize {
self.dir_sizes().filter(|s| *s <= 100000).sum()
}
fn part2(&self) -> usize {
let used = self.sum_size(0);
let unused = 70000000 - used;
let needed = 30000000 - unused;
self.dir_sizes().filter(|s| *s >= needed).min().unwrap()
}
fn sum_size(&self, i: usize) -> usize {
match &self.0[i] {
Node::Directory { children, .. } => children.iter().map(|c| self.sum_size(*c)).sum(),
Node::File { size, .. } => *size,
}
}
}
#[derive(Debug)]
enum Node {
Directory { parent: usize, children: Vec<usize> },
File { parent: usize, size: usize },
}
impl Node {
fn add_child(&mut self, child: usize) {
match self {
Node::Directory { children, .. } => children.push(child),
Node::File { .. } => panic!("cannot add child to file"),
}
}
fn directory(parent: usize) -> Self {
Self::Directory {
parent,
children: Vec::new(),
}
}
fn file(parent: usize, size: usize) -> Self {
Self::File { parent, size }
}
fn parent(&self) -> usize {
match self {
Node::Directory { parent, .. } => *parent,
Node::File { parent, .. } => *parent,
}
}
}
#[derive(Debug)]
enum Line {
CommandUp,
CommandInto,
File(usize),
}
impl FromStr for Line {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "$ cd .." {
Ok(Self::CommandUp)
} else if s.starts_with("$ cd ") {
Ok(Self::CommandInto)
} else if s == "$ ls" || s.starts_with("dir") {
// Ignore ls and directories
Err(())
} else {
let size: usize = s.split(' ').next().unwrap().parse().unwrap();
Ok(Self::File(size))
}
}
}