1use std::collections::HashSet;
2use utils::prelude::*;
3
4#[derive(Clone, Debug)]
6pub struct Day04<'a> {
7 input: &'a str,
8}
9
10impl<'a> Day04<'a> {
11 pub fn new(input: &'a str, _: InputType) -> Result<Self, InputError> {
12 if let Some(w) = input.find(|c: char| !c.is_ascii_lowercase() && !c.is_ascii_whitespace()) {
13 Err(InputError::new(input, w, "expected lowercase letters"))
14 } else {
15 Ok(Self { input })
16 }
17 }
18
19 #[must_use]
20 pub fn part1(&self) -> usize {
21 let mut seen = HashSet::new();
22 self.input
23 .lines()
24 .filter(|line| {
25 seen.clear();
26 line.split_ascii_whitespace().all(|word| seen.insert(word))
27 })
28 .count()
29 }
30
31 #[must_use]
32 pub fn part2(&self) -> usize {
33 let mut seen = HashSet::new();
34 self.input
35 .lines()
36 .filter(|line| {
37 seen.clear();
38 line.split_ascii_whitespace().all(|word| {
39 let mut letters = [0u8; 26];
40 for b in word.bytes() {
41 letters[b as usize - b'a' as usize] += 1;
42 }
43 seen.insert(letters)
44 })
45 })
46 .count()
47 }
48}
49
50examples!(Day04<'_> -> (usize, usize) [
51 {input: "aa bb cc dd ee", part1: 1},
52 {input: "aa bb cc dd aa", part1: 0},
53 {input: "aa bb cc dd aaa", part1: 1},
54 {input: "abcde fghij", part2: 1},
55 {input: "abcde xyz ecdab", part2: 0},
56 {input: "a ab abc abd abf abj", part2: 1},
57 {input: "iiii oiii ooii oooi oooo", part2: 1},
58 {input: "oiii ioii iioi iiio", part2: 0},
59]);