2015-12-11 - Corporate Policy
(original .ipynb)
Puzzle input is a password. Part one involves finding the next password (i.e. "increment" the letter from the right col) until you get a "valid" password according to the three rules defined in the comments. Part two involves finding the next one after that.
puzzle_input_str = open("./puzzle_input/day11.txt").read() # Passwords must include one increasing straight of at least three letters, like abc, bcd, cde, and so on, up to xyz. They cannot skip letters; abd doesn't count. def has_increasing_straight(pwd): for i in range(len(pwd)-2): if pwd[i]+1 == pwd[i+1] and pwd[i]+2 == pwd[i+2]: return True return False # Passwords may not contain the letters i, o, or l, as these letters can be mistaken for other characters and are therefore confusing. def letter(c): n = ord(c) assert n >= ord("a") and n <= ord("z") return n - ord("a") letter_a = letter("a") letter_i = letter("i") letter_o = letter("o") letter_l = letter("l") letter_z = letter("z") def no_confusing_letters(pwd_digits): letters = [d for d in pwd_digits if d == letter_i or d == letter_o or d == letter_l] return 0 == len(letters) # Passwords must contain at least two different, non-overlapping pairs of letters, like aa, bb, or zz. def two_letter_pairs(pwd): i = 0 pairs = 0 while i < len(pwd) - 1: if pwd[i] == pwd[i+1]: pairs += 1 i += 1 i += 1 return pairs >= 2 def valid_password(pwd_digits): return has_increasing_straight(pwd_digits) and no_confusing_letters(pwd_digits) and two_letter_pairs(pwd_digits) def to_digits(pwd): return [letter(c) for c in pwd] def to_letters(pwd_digits): return [chr(ord("a") + c) for c in pwd_digits] assert not valid_password(to_digits("hijklmmn")) assert not valid_password(to_digits("abbceffg")) assert not valid_password(to_digits("abbcegjk")) assert not valid_password(to_digits("abcdefgh")) assert valid_password(to_digits("abcdffaa")) assert not valid_password(to_digits("ghijklmn")) assert valid_password(to_digits("ghjaabcc")) def next_password(pwd_digits): carry = 1 reversed_next_password = [] for digit in reversed(pwd_digits): if carry > 0: digit += carry if digit > letter_z: digit = letter_a carry = 1 else: carry = 0 reversed_next_password.append(digit) return list(reversed(reversed_next_password)) def part_one(input_str): password = to_digits(input_str) while not valid_password(password): password = next_password(password) return "".join(to_letters(password)) assert "abcdffaa" == part_one("abcdefgh") assert "ghjaabcc" == part_one("ghijklmn") print("part one:", part_one(puzzle_input_str))
part one: hepxxyzz
def part_two(input_str): part_one_password = part_one(input_str) next_maybe_password = "".join(to_letters(next_password(to_digits(part_one_password)))) return part_one(next_maybe_password) print("part two:", part_two(puzzle_input_str))
part two: heqaabcc