1use std::collections::HashSet;
2use utils::array::ArrayVec;
3use utils::prelude::*;
4
5#[derive(Clone, Debug)]
7pub struct Day02 {
8 ids: Vec<ArrayVec<u8, 32>>,
9}
10
11impl Day02 {
12 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13 Ok(Self {
14 ids: parser::byte_range(b'a'..=b'z')
15 .repeat_arrayvec(parser::noop(), 1)
16 .parse_lines(input)?,
17 })
18 }
19
20 #[must_use]
21 #[expect(clippy::manual_contains, reason = ".iter().any() is faster here")]
22 pub fn part1(&self) -> u32 {
23 let mut twos = 0;
24 let mut threes = 0;
25 for id in &self.ids {
26 let mut freq = [0u8; 26];
27 for &i in id {
28 freq[(i - b'a') as usize] += 1;
29 }
30 twos += u32::from(freq.iter().any(|&x| x == 2));
31 threes += u32::from(freq.iter().any(|&x| x == 3));
32 }
33 twos * threes
34 }
35
36 #[must_use]
37 pub fn part2(&self) -> String {
38 let mut seen = HashSet::with_capacity(self.ids.len());
39 for column in 0..self.ids[0].capacity() {
40 for mut id in self.ids.iter().map(|id| id.clone().into_array()) {
41 id[column] = 0;
42 if !seen.insert(id) {
43 return id.iter().filter(|&&x| x != 0).map(|&x| x as char).collect();
44 }
45 }
46 seen.clear();
47 }
48 panic!("no solution found")
49 }
50}
51
52examples!(Day02 -> (u32, &'static str) [
53 {input: "abcdef\nbababc\nabbcde\nabcccd\naabcdd\nabcdee\nababab", part1: 12},
54 {input: "abcde\nfghij\nklmno\npqrst\nfguij\naxcye\nwvxyz", part2: "fgij"},
55]);