aoc/year2018/
day02.rs

1//! # Inventory Management System
2use crate::util::hash::*;
3
4pub fn parse(input: &str) -> Vec<&[u8]> {
5    input.lines().map(str::as_bytes).collect()
6}
7
8pub fn part1(input: &[&[u8]]) -> u32 {
9    let mut total_twos = 0;
10    let mut total_threes = 0;
11
12    for &id in input {
13        // Ids are lowercase ASCII only with cardinality of 26.
14        let mut freq = [0; 26];
15        let mut twos = 0;
16        let mut threes = 0;
17
18        for &b in id {
19            let index = (b - b'a') as usize;
20            let current = freq[index];
21
22            match current {
23                0 => (),
24                1 => twos += 1,
25                2 => {
26                    twos -= 1;
27                    threes += 1;
28                }
29                _ => threes -= 1,
30            }
31
32            freq[index] += 1;
33        }
34
35        if twos > 0 {
36            total_twos += 1;
37        }
38        if threes > 0 {
39            total_threes += 1;
40        }
41    }
42
43    total_twos * total_threes
44}
45
46pub fn part2(input: &[&[u8]]) -> String {
47    let width = input[0].len();
48    let mut seen = FastSet::with_capacity(input.len());
49
50    // Use a set to check for duplicates by comparing the prefix and suffix of IDs excluding one
51    // column at a time.
52    for column in 0..width {
53        for &id in input {
54            let prefix = &id[..column];
55            let suffix = &id[column + 1..];
56
57            if !seen.insert([prefix, suffix]) {
58                // Convert to String
59                return prefix.iter().chain(suffix).copied().map(char::from).collect();
60            }
61        }
62
63        seen.clear();
64    }
65
66    unreachable!()
67}