use std::collections::HashMap; const DISALLOWED: [(u8, u8); 4] = [(b'a', b'b'), (b'c', b'd'), (b'p', b'q'), (b'x', b'y')]; const VOWELS: [u8; 5] = [b'a', b'e', b'i', b'o', b'u']; pub fn process_part1(input: &str) -> i32 { input .lines() .map(|line| line.as_bytes()) .map(|line| { let mut num_vowels = 0; let mut has_double = false; if VOWELS.contains(&line[0]) { num_vowels += 1; } for window in line.windows(2) { if DISALLOWED.contains(&(window[0], window[1])) { return 0; } if window[0] == window[1] { has_double = true; } if VOWELS.contains(&window[1]) { num_vowels += 1; } } if num_vowels >= 3 && has_double { return 1; } 0 }) .sum() } // used the following solution to debug // cat input | grep "\(..\).*\1" | grep "\(.\).\1" | wc -l pub fn process_part2(input: &str) -> i32 { input .lines() .map(|line| line.as_bytes()) .map(|line| { let mut pairs = HashMap::new(); let mut has_sandwich = false; for window in line.windows(3) { if window[0] == window[2] { has_sandwich = true; break; } } if !has_sandwich { return 0; } let mut last_pair = "".to_string(); let mut is_valid = true; for window in line.windows(2) { let pair = String::from_utf8(window.to_vec()).unwrap(); if pair == last_pair && is_valid { is_valid = false; continue; } is_valid = true; pairs .entry(pair.clone()) .and_modify(|counter| *counter += 1) .or_insert(1); last_pair = pair; } for (_, count) in pairs.into_iter() { if count >= 2 { return 1; } } 0 }) .sum() } #[cfg(test)] mod tests_5 { use super::*; const INPUT1: &str = "ugknbfddgicrmopn aaa jchzalrnumimnmhp haegwjzuvuyypxyu dvszwmarrgswjxmb"; #[test] fn it_works() { let result = process_part1(INPUT1); assert_eq!(result, 2); } const INPUT2: &str = "qjhvhtzxzqqjkmpb xxyxx uurcxstgmygtbstg ieodomkazucvgmuy"; #[test] fn part2() { let result = process_part2(INPUT2); assert_eq!(result, 2); } }