"""Advent of code 2015 day 11""" def next_password(password: str) -> str: """Increment the password "a" -> "b" "az" -> "ba" """ if password[-1] == 'z': return next_password(password[:-1]) + 'a' else: return password[:-1] + chr(ord(password[-1]) + 1) def has_straight(password: str) -> bool: """Check if a password contains a sequence of at least three consecutive characters""" for i in range(len(password) - 2): if ord(password[i]) + 1 == ord(password[i+1]) and ord(password[i+1]) + 1 == ord(password[i+2]): return True return False def has_pair(password: str) -> bool: """Check if a password contains at least one pair of letters""" for i in range(len(password) - 1): if password[i] == password[i+1]: return True return False def has_pairs(password: str) -> bool: """Check if a password contains at least two different, non-overlapping pairs of letters""" for i in range(len(password) - 1): if password[i] == password[i+1]: return has_pair(password[i+2:]) return False def is_valid(password: str) -> bool: """Check if password is valid Password must: - include one increasing straight of at least three letters - may not contain i, o or l - must contain at least two different, non-overlapping pairs of letters "hijklmmn" -> False "abbceffg" -> True "abbcegjk" -> False """ if not has_straight(password): return False if not has_pairs(password): return False if 'i' in password or 'o' in password or 'l' in password: return False return True def part1(password: str) -> str: """Find the next valid password""" password = next_password(password) while not is_valid(password): password = next_password(password) return password def part2(password: str) -> str: """Find the next valid password""" password = next_password(part1(password)) while not is_valid(password): password = next_password(password) return password if __name__ == '__main__': inp = 'cqjxjnds' print(part1(inp)) print(part2(inp))