year2024/
day25.rs

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