day 19 was quite a doozy!
This commit is contained in:
parent
5135d5c78f
commit
d6e487d400
7
day19/Cargo.toml
Normal file
7
day19/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "day19"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
regex = "1.11.1"
|
126
day19/src/main.rs
Normal file
126
day19/src/main.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, AoC day 13!");
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 2 {
|
||||
println!("wrong number of arguments!");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let file_path = &args[1];
|
||||
|
||||
let binding = fs::read_to_string(file_path)
|
||||
.expect("should be able to read the file");
|
||||
|
||||
let (towels, designs) = binding.split_once("\n\n").expect("should have two sections");
|
||||
|
||||
let all_towels: Vec<&str> = towels.split(", ").collect();
|
||||
|
||||
let re = Regex::new(
|
||||
&format!("^({})+$", all_towels.join("|"))
|
||||
).expect("making the regex");
|
||||
|
||||
let mut count = 0;
|
||||
for line in designs.lines() {
|
||||
if re.is_match(line) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!("found {count} valid designs");
|
||||
|
||||
let mut tree = build_tree(&all_towels);
|
||||
|
||||
//println!("{tree:?}");
|
||||
println!("{} nodes in the tree", tree.len());
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
for line in designs.lines() {
|
||||
count += eat(&mut tree, line);
|
||||
}
|
||||
|
||||
println!("found {count} solutions total");
|
||||
}
|
||||
|
||||
fn eat(tree: &mut Vec<TreeCell>, haystack: &str) -> u128 {
|
||||
let mut heads: HashMap<usize, u128> = HashMap::new();
|
||||
heads.insert(0, 1);
|
||||
|
||||
//println!("examining {haystack}");
|
||||
|
||||
for c in haystack.chars() {
|
||||
// iterating by character
|
||||
let mut new_heads = HashMap::new();
|
||||
|
||||
//println!("looking at {c}; the heads we're tracking are {heads:?}");
|
||||
|
||||
// this first loop branches to the start from valid states
|
||||
for (node_idx, num_heads) in heads.drain() {
|
||||
let TreeCell { next: _, valid } = &tree[node_idx];
|
||||
if *valid {
|
||||
let next_idx = 0;
|
||||
let existing_heads = new_heads.get(&next_idx).unwrap_or(&0);
|
||||
new_heads.insert(next_idx, existing_heads + num_heads);
|
||||
}
|
||||
let existing_heads = new_heads.get(&node_idx).unwrap_or(&0);
|
||||
new_heads.insert(node_idx, existing_heads + num_heads);
|
||||
}
|
||||
|
||||
// this second loop advances all the heads
|
||||
for (node_idx, num_heads) in new_heads.drain() {
|
||||
let TreeCell { next, valid: _ } = &tree[node_idx];
|
||||
if let Some(next_idx) = next.get(&c) {
|
||||
heads.insert(*next_idx, num_heads);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
for (node_idx, number) in heads {
|
||||
if tree[node_idx].valid { count += number; }
|
||||
}
|
||||
//println!("there are {count} heads in success states");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
struct TreeCell {next: HashMap<char, usize>, valid: bool}
|
||||
|
||||
fn build_tree(patterns: &[&str]) -> Vec<TreeCell> {
|
||||
let mut cells = vec![TreeCell {next: HashMap::new(), valid: false}];
|
||||
|
||||
for stripes in patterns {
|
||||
add_to_tree(stripes, &mut cells, 0);
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
fn add_to_tree(pattern: &str, tree: &mut Vec<TreeCell>, index: usize) {
|
||||
match pattern.chars().next() {
|
||||
None => tree[index].valid = true,
|
||||
Some(c) => {
|
||||
if tree[index].next.contains_key(&c) {
|
||||
add_to_tree(&pattern[1..], tree, *tree[index].next.get(&c).unwrap());
|
||||
} else {
|
||||
let new_index = tree.len();
|
||||
let new_treecell = TreeCell { next: HashMap::new(), valid: false };
|
||||
tree.push(new_treecell); // now this is at new_index
|
||||
tree[index].next.insert(c, new_index);
|
||||
|
||||
add_to_tree(&pattern[1..], tree, new_index);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user