aoc/year2015/
day16.rs

1//! # Aunt Sue
2//!
3//! Brute force search through each aunt until we find one that matches all the facts.
4use crate::util::iter::*;
5use crate::util::parse::*;
6
7pub fn parse(input: &str) -> &str {
8    input
9}
10
11pub fn part1(input: &str) -> usize {
12    let predicate = |key: &str, value: &str| match key {
13        "akitas" | "vizslas" => value == "0",
14        "perfumes" => value == "1",
15        "samoyeds" | "cars" => value == "2",
16        "children" | "pomeranians" | "trees" => value == "3",
17        "goldfish" => value == "5",
18        "cats" => value == "7",
19        _ => unreachable!(),
20    };
21    solve(input, predicate)
22}
23
24pub fn part2(input: &str) -> usize {
25    let predicate = |key: &str, value: &str| match key {
26        "akitas" | "vizslas" => value == "0",
27        "perfumes" => value == "1",
28        "samoyeds" | "cars" => value == "2",
29        "children" => value == "3",
30        "pomeranians" => value.unsigned::<u32>() < 3,
31        "goldfish" => value.unsigned::<u32>() < 5,
32        "trees" => value.unsigned::<u32>() > 3,
33        "cats" => value.unsigned::<u32>() > 7,
34        _ => unreachable!(),
35    };
36    solve(input, predicate)
37}
38
39fn solve(input: &str, predicate: impl Fn(&str, &str) -> bool) -> usize {
40    'outer: for (index, line) in input.lines().enumerate() {
41        let tokens = line.split([' ', ':', ',']).filter(|s| !s.is_empty());
42
43        for [key, value] in tokens.chunk::<2>().skip(1) {
44            if !predicate(key, value) {
45                continue 'outer;
46            }
47        }
48
49        return index + 1;
50    }
51
52    unreachable!()
53}