結果

問題 No.2768 Password Crack
ユーザー ThetaTheta
提出日時 2024-07-12 18:19:28
言語 PyPy3
(7.3.15)
結果
WA  
実行時間 -
コード長 3,523 bytes
コンパイル時間 592 ms
コンパイル使用メモリ 82,340 KB
実行使用メモリ 96,748 KB
平均クエリ数 770.40
最終ジャッジ日時 2024-07-12 18:19:40
合計ジャッジ時間 8,597 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 WA -
testcase_01 WA -
testcase_02 WA -
testcase_03 AC 108 ms
83,692 KB
testcase_04 AC 255 ms
96,072 KB
testcase_05 WA -
testcase_06 AC 251 ms
96,028 KB
testcase_07 AC 116 ms
84,716 KB
testcase_08 AC 142 ms
87,932 KB
testcase_09 AC 234 ms
95,888 KB
testcase_10 AC 235 ms
96,028 KB
testcase_11 AC 229 ms
95,768 KB
testcase_12 AC 236 ms
95,820 KB
testcase_13 AC 239 ms
96,748 KB
testcase_14 AC 234 ms
95,516 KB
testcase_15 AC 208 ms
95,132 KB
testcase_16 AC 220 ms
96,300 KB
testcase_17 AC 283 ms
95,844 KB
testcase_18 AC 245 ms
95,888 KB
testcase_19 AC 162 ms
91,636 KB
testcase_20 AC 147 ms
91,096 KB
testcase_21 AC 239 ms
96,172 KB
testcase_22 AC 236 ms
95,008 KB
testcase_23 AC 124 ms
85,704 KB
testcase_24 AC 155 ms
91,960 KB
testcase_25 AC 228 ms
96,484 KB
testcase_26 WA -
testcase_27 AC 219 ms
95,312 KB
testcase_28 WA -
testcase_29 AC 135 ms
87,404 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

from itertools import count, pairwise, product
from random import choices, randint
from string import ascii_lowercase
import sys


def printe(*args, end="\n", **kwargs):
    print(*args, end=end, file=sys.stderr, **kwargs)


class Judge:
    def __init__(
        self,
        N: int = -1,
        is_submit: bool = True,
        ans: str = "",
    ) -> None:
        self.__is_submit = is_submit
        if is_submit or ans:
            self.__ans = ans
        else:
            if N == -1:
                N = randint(1, 100)
            self.__ans = "".join(choices(ascii_lowercase, k=N))
            printe(f"{N=}")
            printe(f"{self.__ans}")
        self.N = len(self.__ans)

    def question(self, password: str) -> int:
        print("?", password, flush=True)
        if self.__is_submit:
            return int(input())
        else:
            ctr = sum(p == a for p, a in zip(password, self.__ans))
            return ctr

    def answer(self, password: str):
        print("!", password)
        if self.__is_submit:
            return
        if self.__ans == password:
            printe("Correct")
        else:
            printe("Incorrect")


class Controler:
    def __init__(self, judge: Judge, max_n: int) -> None:
        self.__judge = judge
        self.__max_n = max_n
        self.__ctr = 0
        self.__is_answered = False
        self.__question_cache: dict[str, int] = {}

    def question(self, password: str | list[str]) -> tuple[bool, int]:
        _password = ""
        if isinstance(password, list):
            _password = "".join(password)
        else:
            _password = password
        if _password in self.__question_cache:
            return True, self.__question_cache[_password]

        if self.__is_answered:
            return False, -1
        if self.__ctr >= self.__max_n:
            self.answer(_password)
            return False, -1
        res = self.__judge.question(_password)
        self.__question_cache[_password] = res
        self.__ctr += 1
        if res == self.__judge.N:
            self.answer(_password)
            return False, -1
        return True, res

    def answer(self, password: str | list[str]):
        if self.__is_answered:
            return
        if isinstance(password, list):
            self.__judge.answer("".join(password))
        else:
            self.__judge.answer(password)
        self.__is_answered = True
        printe(f"{self.__ctr=}")


search_letters = "abcdefghijklmnopqrstuvwxy"


def main():
    N = int(input())

    # judge = Judge(N, False, "z" * N)
    judge = Judge(N)
    password_cand = ["a"] * N
    controler = Controler(judge, 2500)

    cur_digit = 0

    while True:
        if cur_digit >= N:
            break
        is_valid, prev_correct_n = controler.question(password_cand)
        if not is_valid:
            return
        is_found = False
        for l1, l2 in pairwise(search_letters):
            assert password_cand[cur_digit] == l1

            password_cand[cur_digit] = l2
            is_valid, next_correct_n = controler.question(password_cand)
            if prev_correct_n > next_correct_n:
                password_cand[cur_digit] = l1
                is_found = True
                break
            if prev_correct_n < next_correct_n:
                is_found = True
                break
        if not is_found:
            password_cand[cur_digit] = "z"
        cur_digit += 1
    controler.answer(password_cand)


if __name__ == "__main__":
    main()
0