Compare commits

..

1 Commits

Author SHA1 Message Date
f72c93eacc Refactoring 2026-08-01 16:28:33 +02:00

View File

@@ -39,60 +39,67 @@
# 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()]
with open("files/P11.txt") as f:
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:
# increasing straight of at least three letters
def rule_1(password: list[str]) -> bool:
return any(
"".join(chars[i : i + 3]) in ascii_lowercase
for i in range(len(chars) - 2)
ord(password[i]) + 1 == ord(password[i + 1])
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]:
# try with next letter
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_2(password: list[str]) -> bool:
return not any(char in FORBIDDEN_CHARS for char in password)
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 rule_3(password: list[str]) -> bool:
pairs = []
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:
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):
def is_valid_password(password: list[str]) -> bool:
return rule_1(password) and rule_2(password) and rule_3(password)
def increment_password(password: list[str]) -> list[str]:
updated = password.copy()
for index in range(len(updated) - 1, -1, -1):
next_value = ord(updated[index]) + 1
while next_value in FORBIDDEN_ASCII:
next_value += 1
if next_value > ord("z"):
updated[index] = "a"
continue
res = "".join(new_password)
print(f"Santa's next password is {res}")
found = True
updated[index] = chr(next_value)
return updated
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 ---
@@ -101,6 +108,9 @@ def part_1() -> None:
if __name__ == "__main__":
part_1()
first_password = guess_password(password)
print(f"Santa's next password is {first_password}")
# Same code again
part_1()
second_password = guess_password(first_password)
print(f"Santa's next password is {second_password}")