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_eol()
20 .with_eol()
21 .parse_iterator(input)
22 {
23 let (grid, grid_str) = item?;
24
25 let top = grid[0][0];
26 let bottom = grid[6][0];
27 if top == bottom
28 || grid[0][1..].iter().any(|&x| x != top)
29 || grid[6][1..].iter().any(|&x| x != bottom)
30 {
31 return Err(InputError::new(input, grid_str, "expected lock or key"));
32 }
33
34 let mask = grid[1..6]
35 .as_flattened()
36 .iter()
37 .enumerate()
38 .fold(0, |acc, (i, &x)| acc | (u32::from(x == top) << i));
39
40 if top {
41 locks.push(mask);
42 } else {
43 keys.push(mask);
44 }
45 }
46
47 Ok(Self { locks, keys })
48 }
49
50 #[must_use]
51 pub fn part1(&self) -> u32 {
52 let mut total = 0;
53 for &lock in &self.locks {
54 for &key in &self.keys {
55 if lock & key == lock {
56 total += 1;
57 }
58 }
59 }
60 total
61 }
62
63 #[must_use]
64 pub fn part2(&self) -> &'static str {
65 "🎄"
66 }
67}
68
69examples!(Day25 -> (u32, &'static str) [
70 {file: "day25_example0.txt", part1: 3},
71]);