aoc/year2024/
day25.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//! # Code Chronicle
//!
//! Efficiently checks if locks and keys overlap using bitwise logic. The ASCII character
//! `#` (35) is odd and `.` (46) is even so bitwise AND with 1 results in either 1 or 0.
//! The newline character `\n` (10) is even so will result in 0 and not contribute to matches.
//! There are 25 bits plus 4 newline bits so each lock or key can be stored in an `u32`.
//! For example:
//!
//! ```none
//!    #####
//!    ##.##    11011
//!    .#.##    01011
//!    ...## => 00011 => 110110_010110_000110_000100_00010
//!    ...#.    00010
//!    ...#.    00010
//!    .....
//! ```
pub fn parse(input: &str) -> &str {
    input
}

pub fn part1(input: &str) -> u32 {
    let mut slice = input.as_bytes();
    let mut locks = Vec::with_capacity(250);
    let mut keys = Vec::with_capacity(250);
    let mut result = 0;

    while !slice.is_empty() {
        let bits = slice[6..35].iter().fold(0, |bits, &n| (bits << 1) | (n & 1) as u32);

        if slice[0] == b'#' {
            locks.push(bits);
        } else {
            keys.push(bits);
        }

        slice = &slice[43.min(slice.len())..];
    }

    for lock in &locks {
        for key in &keys {
            result += (lock & key == 0) as u32;
        }
    }

    result
}

pub fn part2(_input: &str) -> &'static str {
    "n/a"
}