diff --git a/day16/src/claude.rs b/day16/src/claude.rs new file mode 100644 index 0000000..934b875 --- /dev/null +++ b/day16/src/claude.rs @@ -0,0 +1,72 @@ +use regex::Regex; +use std::collections::HashMap; +use std::fs; + +/// One remembered Aunt Sue: her number and whatever compounds were noted. +#[derive(Debug)] +struct Sue { + number: u32, + properties: HashMap, +} + +/// Parses the puzzle input into a list of `Sue`s. +/// +/// Each line looks like `Sue 1: goldfish: 9, cars: 0, samoyeds: 9`. The +/// number of properties varies per line, so we pull out the `name: count` +/// pairs with a regex rather than assuming a fixed format. +fn parse_sues(input: &str) -> Vec { + let line_re = Regex::new(r"^Sue (\d+): (.+)$").unwrap(); + let property_re = Regex::new(r"(\w+): (\d+)").unwrap(); + + input + .lines() + .filter_map(|line| { + let caps = line_re.captures(line)?; + let number = caps[1].parse().unwrap(); + let properties = property_re + .captures_iter(&caps[2]) + .map(|prop| (prop[1].to_string(), prop[2].parse().unwrap())) + .collect(); + + Some(Sue { number, properties }) + }) + .collect() +} + +/// The exact readings from the MFCSAM. +fn target_properties() -> HashMap<&'static str, u32> { + HashMap::from([ + ("children", 3), + ("cats", 7), + ("samoyeds", 2), + ("pomeranians", 3), + ("akitas", 0), + ("vizslas", 0), + ("goldfish", 5), + ("trees", 3), + ("cars", 2), + ("perfumes", 1), + ]) +} + +/// A Sue matches if every compound she's remembered for equals the target +/// reading exactly. Properties she isn't remembered for are simply skipped, +/// per the puzzle's "missing things aren't zero" rule. +fn matches_target(sue: &Sue, target: &HashMap<&str, u32>) -> bool { + sue.properties + .iter() + .all(|(name, &count)| target.get(name.as_str()) == Some(&count)) +} + +fn main() { + let input = fs::read_to_string("input.txt").expect("failed to read input.txt"); + let sues = parse_sues(&input); + let target = target_properties(); + + let real_sue = sues + .iter() + .find(|sue| matches_target(sue, &target)) + .expect("no Sue matched the MFCSAM readings"); + + println!("Sue {} gave the gift.", real_sue.number); +}