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
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]);