use itertools::Itertools; #[cfg(debug_assertions)] const INPUT: &str = "example.txt"; #[cfg(not(debug_assertions))] const INPUT: &str = "input.txt"; fn main() { let binding = std::fs::read_to_string(INPUT).unwrap(); let data: Vec<_> = binding.lines().map(Address::parse).collect(); part1(&data); part2(&data); } fn part1(addresses: &[Address]) { let result = addresses.iter().filter(|a| a.supports_tls()).count(); println!("{result}"); } fn part2(addresses: &[Address]) { let result = addresses.iter().filter(|a| a.supports_ssl()).count(); println!("{result}"); } #[derive(Debug)] struct Address<'a> { supernets: Vec<&'a str>, hypernets: Vec<&'a str>, } impl<'a> Address<'a> { fn supports_tls(&self) -> bool { self.supernets.iter().any(|s| contains_like_abba(s)) && self.hypernets.iter().all(|h| !contains_like_abba(h)) } fn supports_ssl(&self) -> bool { for aba in self.supernets.iter().flat_map(|s| find_like_aba(s)) { if self .hypernets .iter() .any(|h| contains_like_bab(h.to_string(), &aba)) { return true; } } false } fn parse(s: &'a str) -> Self { let mut supernets = Vec::new(); let mut hypernets = Vec::new(); for (i, part) in s.split(&['[', ']']).enumerate() { if i % 2 == 0 { supernets.push(part); } else { hypernets.push(part); } } Self { supernets, hypernets, } } } fn find_like_aba(s: &str) -> Vec { let mut result = vec![]; for (a, b, c) in s.chars().tuple_windows() { if a == c && a != b { result.push(format!("{a}{b}{c}")); } } result } fn contains_like_bab(s: String, aba: &str) -> bool { let mut chars = aba.chars(); let a = chars.next().unwrap(); let b = chars.next().unwrap(); for (x, y, z) in s.chars().tuple_windows() { if x == b && y == a && z == b { return true; } } false } fn contains_like_abba(s: &str) -> bool { for (a, b, c, d) in s.chars().tuple_windows() { if a == d && b == c && a != b { return true; } } false } #[cfg(test)] mod tests { use crate::contains_like_abba; #[test] fn abba() { assert!(contains_like_abba("abba")); assert!(!contains_like_abba("abcd")); assert!(!contains_like_abba("aaaa")); assert!(!contains_like_abba("aaaaaa")); assert!(contains_like_abba("aaabba")); assert!(!contains_like_abba("qrst")); assert!(!contains_like_abba("tyui")); assert!(contains_like_abba("ioxxoj")); assert!(!contains_like_abba("zxcvbn")); } }