pub fn process_part1(input: &str) -> String { let mut password = input.to_string(); loop { password = increment(&password); if password.contains("i") || password.contains("o") || password.contains("l") { continue; } if !has_straight(&password) { continue; } if num_pairs(&password) < 2 { continue; } return password; } } fn has_straight(password: &str) -> bool { for window in password.as_bytes().windows(3) { let (a, b, c) = (window[0], window[1], window[2]); let (inc_b, inc_c) = (increment_letter(a), increment_letter(b)); if b == inc_b.0 && c == inc_c.0 && !(inc_b.1 || inc_c.1) { return true; } } false } fn num_pairs(password: &str) -> u32 { let mut num_pairs = 0; let mut was_last_pair = false; password.as_bytes().windows(2).for_each(|window| { if window[0] == window[1] && !was_last_pair { num_pairs += 1; was_last_pair = true; } else { was_last_pair = false; } }); num_pairs } fn increment(password: &str) -> String { let mut password_bytes = password.as_bytes().to_vec(); password_bytes.reverse(); let mut new_password_bytes = vec![]; let mut increment_next = true; for letter in password_bytes { if increment_next { let (new_letter, overflow) = increment_letter(letter); new_password_bytes.push(new_letter); increment_next = overflow; } else { new_password_bytes.push(letter); } } if increment_next { new_password_bytes.push(b'a'); } new_password_bytes.reverse(); String::from_utf8(new_password_bytes).unwrap() } fn increment_letter(letter: u8) -> (u8, bool) { if letter == b'z' { (b'a', true) } else { (letter + 1, false) } }