done with day 7
This commit is contained in:
parent
d4af3e7c26
commit
fd29d5cf87
3 changed files with 129 additions and 0 deletions
|
@ -8,5 +8,6 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aoc-runner = "0.3"
|
aoc-runner = "0.3"
|
||||||
aoc-runner-derive = "0.3"
|
aoc-runner-derive = "0.3"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
#itertools = "0.10.5"
|
#itertools = "0.10.5"
|
||||||
regex = "1.7"
|
regex = "1.7"
|
||||||
|
|
127
2022-aoc/src/d7.rs
Normal file
127
2022-aoc/src/d7.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
use aoc_runner_derive::{aoc as aoc_run, aoc_generator};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use regex::Regex;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
type Files = HashMap<String, u32>;
|
||||||
|
type Dirs = HashMap<String, Node>;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct Node {
|
||||||
|
files: HashSet<String>,
|
||||||
|
dirs: HashSet<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Parsing {
|
||||||
|
Command,
|
||||||
|
Listing,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn command(c: &str, cwd: &mut Vec<String>) -> Parsing {
|
||||||
|
if c.starts_with("$ cd") {
|
||||||
|
let dest = String::from_utf8(c.as_bytes()[5..].to_vec()).unwrap();
|
||||||
|
if dest == ".." {
|
||||||
|
let _ = cwd.pop();
|
||||||
|
} else {
|
||||||
|
cwd.push(dest);
|
||||||
|
}
|
||||||
|
return Parsing::Command;
|
||||||
|
}
|
||||||
|
Parsing::Listing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listing(c: &str, cwd: &[String], files: &mut Files, node: &mut Node) {
|
||||||
|
lazy_static! {
|
||||||
|
static ref FILE: Regex = Regex::new(r"^(\d+) ([a-z.]+$)").unwrap();
|
||||||
|
static ref DIR: Regex = Regex::new(r"^dir ([a-z.]+$)").unwrap();
|
||||||
|
}
|
||||||
|
let mut path = cwd.to_vec();
|
||||||
|
if let Some(cap) = FILE.captures(c) {
|
||||||
|
let sz = cap[1].parse().unwrap();
|
||||||
|
let name = cap[2].to_owned();
|
||||||
|
path.push(name);
|
||||||
|
let name = path.join("/");
|
||||||
|
files.insert(name.clone(), sz);
|
||||||
|
node.files.insert(name);
|
||||||
|
} else if let Some(cap) = DIR.captures(c) {
|
||||||
|
let name = cap[1].to_owned();
|
||||||
|
path.push(name);
|
||||||
|
let name = path.join("/");
|
||||||
|
node.dirs.insert(name);
|
||||||
|
} else {
|
||||||
|
dbg!("what the fuck", c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_generator(day7)]
|
||||||
|
fn parse_input_day1(input: &str) -> (Dirs, Files) {
|
||||||
|
let mut dirs = Dirs::new();
|
||||||
|
let mut files = Files::new();
|
||||||
|
let mut cwd = Vec::new();
|
||||||
|
let mut pstatus = Parsing::Command;
|
||||||
|
let mut node = Node::default();
|
||||||
|
for line in input.lines() {
|
||||||
|
match pstatus {
|
||||||
|
Parsing::Command => {
|
||||||
|
if line.starts_with('$') {
|
||||||
|
pstatus = command(line, &mut cwd);
|
||||||
|
} else {
|
||||||
|
pstatus = Parsing::Listing;
|
||||||
|
listing(line, &cwd, &mut files, &mut node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Parsing::Listing => {
|
||||||
|
if line.starts_with('$') {
|
||||||
|
// we are just finished with a listing, so add the node to the map
|
||||||
|
dirs.insert(cwd.join("/"), node);
|
||||||
|
node = Node::default();
|
||||||
|
pstatus = command(line, &mut cwd);
|
||||||
|
} else {
|
||||||
|
listing(line, &cwd, &mut files, &mut node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dirs.insert(cwd.join("/"), node);
|
||||||
|
(dirs, files)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_run(day7, part1)]
|
||||||
|
fn part1((dirs, files): &(Dirs, Files)) -> u32 {
|
||||||
|
let mut sizes = Vec::new();
|
||||||
|
for (name, _node) in dirs.iter() {
|
||||||
|
sizes.push((name, size(name, dirs, files)));
|
||||||
|
}
|
||||||
|
sizes
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|e| if e.1 <= 100000 { Some(e.1) } else { None })
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_run(day7, part2)]
|
||||||
|
fn part2((dirs, files): &(Dirs, Files)) -> u32 {
|
||||||
|
let mut sizes = Vec::new();
|
||||||
|
for (name, _node) in dirs.iter() {
|
||||||
|
sizes.push((name, size(name, dirs, files)));
|
||||||
|
}
|
||||||
|
let total = size("/", dirs, files);
|
||||||
|
let avail = 70_000_000 - total;
|
||||||
|
let needed = 30_000_000 - avail;
|
||||||
|
|
||||||
|
sizes.sort_by(|a, b| (a.1).cmp(&b.1));
|
||||||
|
sizes.iter().find(|x| x.1 >= needed).unwrap().1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(name: &str, dirs: &Dirs, files: &Files) -> u32 {
|
||||||
|
let mut out = 0;
|
||||||
|
if let Some(node) = dirs.get(name) {
|
||||||
|
for file in node.files.iter() {
|
||||||
|
out += files.get(file).unwrap();
|
||||||
|
}
|
||||||
|
for dir in node.dirs.iter() {
|
||||||
|
out += size(dir, dirs, files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
|
@ -6,5 +6,6 @@ mod d3;
|
||||||
mod d4;
|
mod d4;
|
||||||
mod d5;
|
mod d5;
|
||||||
mod d6;
|
mod d6;
|
||||||
|
mod d7;
|
||||||
|
|
||||||
aoc_lib! { year = 2022 }
|
aoc_lib! { year = 2022 }
|
||||||
|
|
Loading…
Reference in a new issue