Compare commits
1 Commits
6d0c9194dd
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f72c93eacc |
@@ -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}")
|
||||||
|
|||||||
Reference in New Issue
Block a user