|
| 1 | +use std::collections::HashSet; |
| 2 | +use utils::array::ArrayVec; |
| 3 | +use utils::prelude::*; |
| 4 | + |
| 5 | +/// Finding near-match IDs. |
| 6 | +#[derive(Clone, Debug)] |
| 7 | +pub struct Day02 { |
| 8 | + ids: Vec<ArrayVec<u8, 32>>, |
| 9 | +} |
| 10 | + |
| 11 | +impl 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 | + |
| 52 | +examples!(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 | +]); |
0 commit comments