From 4c3960b56e872c46346d933a850bca2ebac98854 Mon Sep 17 00:00:00 2001 From: daviddoji Date: Mon, 13 Jun 2022 21:04:02 +0200 Subject: [PATCH] Solution to problem 11 in Python --- src/Year_2015/P11.py | 105 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/Year_2015/P11.py diff --git a/src/Year_2015/P11.py b/src/Year_2015/P11.py new file mode 100644 index 0000000..4d93578 --- /dev/null +++ b/src/Year_2015/P11.py @@ -0,0 +1,105 @@ +# --- Day 11: Corporate Policy --- + +# Santa's previous password expired, and he needs help choosing a new one. + +# To help him remember his new password after the old one expires, Santa has +# devised a method of coming up with a password based on the previous one. +# Corporate policy dictates that passwords must be exactly eight lowercase +# letters (for security reasons), so he finds his new password by incrementing +# his old password string repeatedly until it is valid. + +# Incrementing is just like counting with numbers: xx, xy, xz, ya, yb, and so +# on. Increase the rightmost letter one step; if it was z, it wraps around to +# a, and repeat with the next letter to the left until one doesn't wrap around. + +# Unfortunately for Santa, a new Security-Elf recently started, and he has +# imposed some additional password requirements: + +# 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. +# Passwords may not contain the letters i, o, or l, as these letters can be +# mistaken for other characters and are therefore confusing. +# Passwords must contain at least two different, non-overlapping pairs of +# letters, like aa, bb, or zz. + +# For example: + +# hijklmmn meets the first requirement (because it contains the straight +# hij) but fails the second requirement requirement (because it contains i and +# l). +# abbceffg meets the third requirement (because it repeats bb and ff) but +# fails the first requirement. +# abbcegjk fails the third requirement, because it only has one double +# letter (bb). +# The next password after abcdefgh is abcdffaa. +# The next password after ghijklmn is ghjaabcc, because you eventually skip +# all the passwords that start with ghi..., since i is not allowed. + +# Given Santa's current password (your puzzle input), what should his next +# password be? + +import re +from string import ascii_lowercase + +with open("files/P11.txt", "r") as f: + password = [c for c in f.read().strip()] + +forbidden_chars = {105, 108, 111} + + +def rule_1(chars: list[str]) -> bool: + # increasing straight of at least three letters + return any( + "".join(chars[i : i + 3]) in ascii_lowercase + for i in range(len(chars) - 2) + ) + + +def rule_2(chars: list[str], pos: int) -> list[str]: + # not contain the letters i, o, or l + a = ord(chars[pos]) + 1 + # rule # 2 + if a in forbidden_chars: + a += 1 + # wraps around to a + if a > 122: + a = 97 + chars[pos] = chr(a) + rule_2(chars, pos - 1) + else: + chars[pos] = chr(a) + return chars + + +def rule_3(chars: list[str]) -> bool: + # at least two different, non-overlapping pairs of letters + return bool(re.search(r"(\w)\1.*(\w)\2", "".join(chars))) + + +def part_1() -> None: + new_password = password + found = False + while not found: + new_password = rule_2(new_password, -1) + # rule 1 + if not rule_1(new_password): + continue + # rule # 3 + if not rule_3(new_password): + continue + + res = "".join(new_password) + print(f"Santa's next password is {res}") + found = True + + +# --- Part Two --- + +# Santa's password expired again. What's the next one? + + +if __name__ == "__main__": + part_1() + # Same code again + part_1()