Refactoring

This commit is contained in:
2026-08-01 16:28:33 +02:00
parent 6d0c9194dd
commit f72c93eacc

View File

@@ -39,60 +39,67 @@
# Given Santa's current password (your puzzle input), what should his next # Given Santa's current password (your puzzle input), what should his next
# password be? # password be?
import re
from string import ascii_lowercase
with open("files/P11.txt", "r") as f: with open("files/P11.txt") as f:
password = [c for c in f.read().strip()] password = f.read().strip()
forbidden_chars = {105, 108, 111} FORBIDDEN_CHARS = {"i", "o", "l"}
FORBIDDEN_ASCII = {ord(char) for char in FORBIDDEN_CHARS}
def rule_1(chars: list[str]) -> bool: def rule_1(password: list[str]) -> bool:
# increasing straight of at least three letters
return any( return any(
"".join(chars[i : i + 3]) in ascii_lowercase ord(password[i]) + 1 == ord(password[i + 1])
for i in range(len(chars) - 2) and ord(password[i + 1]) + 1 == ord(password[i + 2])
for i in range(len(password) - 2)
) )
def rule_2(chars: list[str], pos: int) -> list[str]: def rule_2(password: list[str]) -> bool:
# try with next letter return not any(char in FORBIDDEN_CHARS for char in password)
a = ord(chars[pos]) + 1
# not contain the letters i, o, or l
if a in forbidden_chars:
a += 1
# wraps around to a
if a > 122:
a = 97
chars[pos] = chr(a)
# change now previous letter also
rule_2(chars, pos - 1)
else:
chars[pos] = chr(a)
return chars
def rule_3(chars: list[str]) -> bool: def rule_3(password: list[str]) -> bool:
# at least two different, non-overlapping pairs of letters pairs = []
return bool(re.search(r"(\w)\1.*(\w)\2", "".join(chars))) index = 0
while index < len(password) - 1:
if password[index] == password[index + 1]:
pairs.append(password[index])
index += 2
else:
index += 1
return len(set(pairs)) >= 2
def part_1() -> None: def is_valid_password(password: list[str]) -> bool:
new_password = password return rule_1(password) and rule_2(password) and rule_3(password)
found = False
while not found:
new_password = rule_2(new_password, -1) def increment_password(password: list[str]) -> list[str]:
# rule 1 updated = password.copy()
if not rule_1(new_password):
continue for index in range(len(updated) - 1, -1, -1):
# rule # 3 next_value = ord(updated[index]) + 1
if not rule_3(new_password):
while next_value in FORBIDDEN_ASCII:
next_value += 1
if next_value > ord("z"):
updated[index] = "a"
continue continue
res = "".join(new_password) updated[index] = chr(next_value)
print(f"Santa's next password is {res}") return updated
found = True
raise ValueError("Password overflowed")
def guess_password(start_password: str) -> str:
password = list(start_password)
while True:
password = increment_password(password)
if is_valid_password(password):
return "".join(password)
# --- Part Two --- # --- Part Two ---
@@ -101,6 +108,9 @@ def part_1() -> None:
if __name__ == "__main__": if __name__ == "__main__":
part_1() first_password = guess_password(password)
print(f"Santa's next password is {first_password}")
# Same code again # Same code again
part_1() second_password = guess_password(first_password)
print(f"Santa's next password is {second_password}")