Skip to main content

year2020/
day06.rs

1use utils::prelude::*;
2
3/// Summing the sizes of set unions and intersections.
4#[derive(Clone, Debug)]
5pub struct Day06 {
6    part1: u32,
7    part2: u32,
8}
9
10const ALL_ANSWERS: u32 = (1 << 26) - 1;
11const ANSWER_BITS: [Option<u32>; 256] = {
12    let mut bits = [None; 256];
13    let mut i = 0u8;
14    while i < 26 {
15        bits[(b'a' + i) as usize] = Some(1 << i);
16        i += 1;
17    }
18    bits
19};
20
21impl Day06 {
22    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
23        let bytes = input.as_bytes();
24        let (mut part1, mut part2) = (0, 0);
25        let (mut any, mut every, mut person) = (0u32, ALL_ANSWERS, 0u32);
26
27        for (index, &b) in bytes.iter().enumerate() {
28            if let Some(answer) = ANSWER_BITS[b as usize] {
29                person |= answer;
30            } else if b == b'\n' {
31                if person != 0 {
32                    any |= person;
33                    every &= person;
34                    person = 0;
35                } else {
36                    if any == 0 {
37                        return Err(InputError::new(input, index, "expected lowercase letter"));
38                    }
39                    part1 += any.count_ones();
40                    part2 += every.count_ones();
41                    (any, every) = (0, ALL_ANSWERS);
42                }
43            } else if !(b == b'\r' && bytes.get(index + 1) == Some(&b'\n')) {
44                return Err(InputError::new(input, index, "expected lowercase letter"));
45            }
46        }
47
48        if person != 0 {
49            any |= person;
50            every &= person;
51        }
52
53        if any == 0 {
54            return Err(InputError::new(
55                input,
56                input.len(),
57                "expected lowercase letter",
58            ));
59        }
60        part1 += any.count_ones();
61        part2 += every.count_ones();
62
63        Ok(Self { part1, part2 })
64    }
65
66    #[must_use]
67    pub fn part1(&self) -> u32 {
68        self.part1
69    }
70
71    #[must_use]
72    pub fn part2(&self) -> u32 {
73        self.part2
74    }
75}
76
77examples!(Day06 -> (u32, u32) [
78    {input: "abcx\nabcy\nabcz", part1: 6},
79    {input: "abc\n\na\nb\nc\n\nab\nac\n\na\na\na\na\n\nb", part1: 11, part2: 6},
80]);