broken implementation of 7.1
This commit is contained in:
parent
a998e68b71
commit
393db1d3bf
42
2022/Cargo.lock
generated
42
2022/Cargo.lock
generated
@ -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"
|
||||
|
@ -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
181
2022/src/day7.rs
Normal 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}");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user