use aoc_runner_derive::aoc; #[aoc(day11, part1)] fn part1(input: &str) -> String { PasswordCounter::from(input.to_owned()).find(|p| { let r1 = rule1(&p); let r2 = rule2(&p); let r3 = rule3(&p); r1 && r2 && r3 }).unwrap() } #[aoc(day11, part2)] fn part2(input: &str) -> String { PasswordCounter::from(input.to_owned()).filter(|p| { let r1 = rule1(&p); let r2 = rule2(&p); let r3 = rule3(&p); r1 && r2 && r3 }) .skip(1) .next().unwrap() } fn rule1(pw: &str) -> bool { let pw = pw.as_bytes(); for i in 0..pw.len() - 2 { if pw[i + 1] == pw[i] + 1 && pw[i + 2] == pw[i] + 2 { return true; } } false } fn rule2(pw: &str) -> bool { !pw.contains(['i', 'o', 'l']) } fn rule3(pw: &str) -> bool { let mut pair_one = None; let pw = pw.as_bytes(); for i in 0..pw.len() - 1 { if pw[i] == pw[i + 1] { if let Some(b) = pair_one { if b != pw[i] { return true; } } else { pair_one = Some(pw[i]); } } } false } struct PasswordCounter { current: [u8; 8], } impl PasswordCounter { fn from(seed: String) -> Self { let mut current = [0u8; 8]; for i in 0..8 { current[i] = seed.as_bytes()[i]; } PasswordCounter { current } } } impl Iterator for PasswordCounter { type Item = String; fn next(&mut self) -> Option { let pw = &mut self.current; for i in (0..pw.len()).rev() { pw[i] += 1; if pw[i] != b'z' + 1 { break; } pw[i] = b'a'; } Some(String::from_iter(self.current.iter().map(|b| *b as char))) } } #[cfg(test)] mod tests {}