Co-authored-by: Mikael CAPELLE <mikael.capelle@thalesaleniaspace.com> Co-authored-by: Mikaël Capelle <capelle.mikael@gmail.com> Reviewed-on: #3
50 lines
1.1 KiB
Python
50 lines
1.1 KiB
Python
import itertools
|
|
from typing import Any, Iterator
|
|
|
|
from ..base import BaseSolver
|
|
|
|
|
|
def is_valid(p: str) -> bool:
|
|
if any(c in "iol" for c in p):
|
|
return False
|
|
|
|
if not any(
|
|
ord(a) + 1 == ord(b) and ord(b) + 1 == ord(c)
|
|
for a, b, c in zip(p, p[1:], p[2:])
|
|
):
|
|
return False
|
|
|
|
if sum(len(list(g)) >= 2 for _, g in itertools.groupby(p)) < 2:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
assert not is_valid("hijklmmn")
|
|
assert not is_valid("abbceffg")
|
|
assert not is_valid("abbcegjk")
|
|
assert is_valid("abcdffaa")
|
|
assert is_valid("ghjaabcc")
|
|
|
|
|
|
def increment(p: str) -> str:
|
|
if p[-1] == "z":
|
|
return increment(p[:-1]) + "a"
|
|
elif p[-1] in "iol":
|
|
return p[:-1] + chr(ord(p[-1]) + 2)
|
|
else:
|
|
return p[:-1] + chr(ord(p[-1]) + 1)
|
|
|
|
|
|
def find_next_password(p: str) -> str:
|
|
while not is_valid(p):
|
|
p = increment(p)
|
|
return p
|
|
|
|
|
|
class Solver(BaseSolver):
|
|
def solve(self, input: str) -> Iterator[Any]:
|
|
answer_1 = find_next_password(input)
|
|
yield answer_1
|
|
yield find_next_password(increment(answer_1))
|