1use 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}