broken implementation of 7.1

This commit is contained in:
Joseph Montanaro 2022-12-07 22:06:52 -08:00
parent a998e68b71
commit 393db1d3bf
3 changed files with 226 additions and 0 deletions

42
2022/Cargo.lock generated
View File

@ -5,3 +5,45 @@ version = 3
[[package]]
name = "advent-2022"
version = "0.1.0"
dependencies = [
"lazy_static",
"regex",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "regex"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"

View File

@ -31,6 +31,9 @@ path = "src/day5.rs"
name = "day6"
path = "src/day6.rs"
[[bin]]
name = "day7"
path = "src/day7.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

181
2022/src/day7.rs Normal file
View File

@ -0,0 +1,181 @@
use std::collections::HashMap;
use lazy_static::lazy_static;
use regex::Regex;
struct Directory {
name: String,
children: Vec<Node>,
}
struct File {
name: String,
size: usize,
}
enum Node {
Branch(Directory),
Leaf(File),
}
lazy_static! {
static ref CMD_CD: Regex = Regex::new(r"^\$ cd (\w+)$").unwrap();
static ref CMD_LS: Regex = Regex::new(r"^\$ ls$").unwrap();
static ref DIR_LISTING: Regex = Regex::new(r"^dir (\w+)$").unwrap();
static ref FILE_LISTING: Regex = Regex::new(r"^(\d+) (\w+)$").unwrap();
}
struct DirListing {
name: String,
children: Vec<usize>,
parent: Option<usize>,
}
enum NodeListing {
Branch(DirListing),
Leaf(File),
}
fn build_map(data: &str) -> Result<HashMap<usize, NodeListing>, String> {
let root = DirListing {
name: "".to_string(),
children: vec![],
parent: None,
};
let mut map = HashMap::new();
map.insert(0, NodeListing::Branch(root));
let mut stack: Vec<usize> = vec![];
stack.push(0);
'lines: for line in data.trim().lines() {
if CMD_LS.is_match(line) {continue;}
if let Some(m) = CMD_CD.find_iter(line).next() {
let name = m.as_str();
if name == ".." {
stack.pop();
continue;
}
let current_dir = match map.get(&stack.last().unwrap()).unwrap() {
NodeListing::Branch(dir) => dir,
_ => unreachable!(),
};
for id in current_dir.children {
let child_name = match map.get(&id).unwrap() {
NodeListing::Branch(dir) => dir.name,
NodeListing::Leaf(file) => file.name,
};
if child_name == name {
stack.push(id);
continue 'lines;
}
}
return Err(format!("Attempted to cd into directory before ls-ing it: {}", line.to_string()));
}
if let Some(m) = DIR_LISTING.find_iter(line).next() {
let parent_id = stack.last().unwrap();
let parent = match map.get_mut(parent_id).unwrap() {
NodeListing::Branch(dir) => dir,
_ => unreachable!(),
};
let dir = DirListing {
name: m.as_str().to_string(),
children: vec![],
parent: Some(*parent_id),
};
// this is safe as long as we never remove anything from the map while we're building it
let dir_id = map.len();
map.insert(dir_id, NodeListing::Branch(dir));
parent.children.push(dir_id);
continue;
}
let matches = FILE_LISTING.find_iter(line);
if let (Some(s), Some(n)) = (matches.next(), matches.next()) {
let name = n.as_str().to_string();
let size = s.as_str().parse::<usize>()
.map_err(|_e| format!("Invalid file size: {}", line.to_string()))?;
let file_id = map.len();
let file = File {name, size};
map.insert(file_id, NodeListing::Leaf(file));
let parent = match map.get_mut(stack.last().unwrap()).unwrap() {
NodeListing::Branch(dir) => dir,
_ => unreachable!(),
};
parent.children.push(file_id);
continue;
}
return Err(format!("Could not interpret line: {line}"));
}
Ok(map)
}
fn build_tree(map: &HashMap<usize, NodeListing>, root:&DirListing) -> Directory {
let root_listing = map.get(&root_id).unwrap();
let root_children = Vec::new();
for child_id in root_listing.children {
match map.get(&child_id).unwrap() {
NodeListing::Leaf(file) => {
root_children.push(Node::Leaf(file));
},
NodeListing::Branch(dir_listing) => {
let dir = build_tree(map, child_id);
root_children.push(Node::Branch(dir))
},
}
}
Directory {
name: root_listing.name.clone(),
children: root_children,
}
}
fn get_sizes(root: &Directory, mut sizes: Vec<usize>) -> (usize, Vec<usize>) {
let dir_size = 0;
let mut returned_sizes;
for child in root.children {
match child {
Node::Leaf(file) => dir_size += file.size,
Node::Branch(dir) => {
let (child_size, rs) = get_sizes(dir, sizes);
returned_sizes = rs;
dir_size += child_size;
},
}
}
returned_sizes.push(dir_size);
returned_sizes
}
fn main() -> Result<(), String> {
let map = build_map(data);
let tree = build_tree(map, 0);
let (_total_size, dir_sizes) = get_sizes(&tree, vec![]);
let part1_sizes = dir_sizes.iter()
.filter(|s| s <= 100000)
.sum();
println!("Part 1: {part1_sizes}");
}