1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day25 {
6 locks: Vec<u32>,
7 keys: Vec<u32>,
8}
9
10impl Day25 {
11 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
12 let mut locks = Vec::with_capacity(250);
13 let mut keys = Vec::with_capacity(250);
14
15 for item in parser::byte_map!(b'#' => true, b'.' => false)
16 .repeat_n::<5, _>(parser::noop())
17 .repeat_n::<7, _>(parser::eol())
18 .with_consumed()
19 .with_suffix(parser::eol().then(parser::eol()))
20 .parse_iterator(input)
21 {
22 let (grid, grid_str) = item?;
23
24 let top = grid[0][0];
25 let bottom = grid[6][0];
26 if top == bottom
27 || grid[0][1..].iter().any(|&x| x != top)
28 || grid[6][1..].iter().any(|&x| x != bottom)
29 {
30 return Err(InputError::new(input, grid_str, "expected lock or key"));
31 }
32
33 let mask = grid[1..6]
34 .as_flattened()
35 .iter()
36 .enumerate()
37 .fold(0, |acc, (i, &x)| acc | (u32::from(x == top) << i));
38
39 if top {
40 locks.push(mask);
41 } else {
42 keys.push(mask);
43 }
44 }
45
46 Ok(Self { locks, keys })
47 }
48
49 #[must_use]
50 pub fn part1(&self) -> u32 {
51 let mut total = 0;
52 for &lock in &self.locks {
53 for &key in &self.keys {
54 if lock & key == lock {
55 total += 1;
56 }
57 }
58 }
59 total
60 }
61
62 #[must_use]
63 pub fn part2(&self) -> &'static str {
64 "🎄"
65 }
66}
67
68examples!(Day25 -> (u32, &'static str) [
69 {file: "day25_example0.txt", part1: 3},
70]);