use crate::prelude::*; pub type T = (String, M, Vec, u32); pub type I = Vec; pub type O = u32; fn _parse (data: &str) -> I { data.lines().map(|line| { let mut parts = line.split('-').collect_vec(); let last = parts.pop().unwrap(); let rest = parts.join(" "); let m = parts.into_iter().map(|p| p.chars()).flatten().counts(); let (number, checksum) = last.split_once('[').unwrap(); let number = number.parse().unwrap(); let checksum = checksum.trim_matches(']').chars().collect(); (rest, m, checksum, number) }).collect() } fn _solve <'a> (data: &'a I) -> impl Iterator { data.into_iter().filter_map(|(st, m, checksum, num)| { let mut m = m.into_iter().collect_vec(); m.sort_by(|a, b| match b.1.cmp(&a.1) { Or::Equal => a.0.cmp(&b.0), e => e }); if checksum.into_iter().zip(m.into_iter()).all(|(&l, (&r, _))| l == r) { Some((st, num)) } else { None } }) } fn _silver (data: &I) -> O { _solve(data).map(|(_, num)| num).sum() } fn _gold (data: &I) -> O { *_solve(data).find(|(s, num)| { let mut s = s.chars().collect_vec(); for c in s.iter_mut() { match *c { ' ' => (), a => { *c = ((((a as u8 - b'a') as u32 + *num) % 26) + b'a' as u32) as u8 as char; } } } let s = s.into_iter().collect::(); s.contains("north") }).unwrap().1 } #[cfg(test)] mod test { use super::*; fn read () -> I { let data = inc!(4); _parse(data) } #[test] fn silver () { let data = read(); let ans = _silver(&data); assert_eq!(ans, 278221) } #[test] fn gold () { let data = read(); let ans = _gold(&data); assert_eq!(ans, 267) } }