結果

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

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 WA -
testcase_01 WA -
testcase_02 WA -
testcase_03 AC 100 ms
83,288 KB
testcase_04 AC 220 ms
95,960 KB
testcase_05 WA -
testcase_06 AC 217 ms
96,088 KB
testcase_07 AC 109 ms
83,544 KB
testcase_08 AC 134 ms
85,080 KB
testcase_09 AC 211 ms
95,704 KB
testcase_10 AC 219 ms
95,960 KB
testcase_11 AC 215 ms
95,960 KB
testcase_12 AC 219 ms
95,704 KB
testcase_13 AC 218 ms
96,080 KB
testcase_14 AC 214 ms
95,960 KB
testcase_15 AC 191 ms
94,936 KB
testcase_16 AC 212 ms
96,472 KB
testcase_17 AC 211 ms
95,960 KB
testcase_18 AC 213 ms
96,472 KB
testcase_19 AC 155 ms
90,200 KB
testcase_20 AC 142 ms
89,560 KB
testcase_21 AC 211 ms
95,960 KB
testcase_22 AC 187 ms
95,192 KB
testcase_23 AC 112 ms
84,312 KB
testcase_24 AC 141 ms
89,304 KB
testcase_25 AC 215 ms
95,704 KB
testcase_26 WA -
testcase_27 AC 185 ms
94,808 KB
testcase_28 WA -
testcase_29 AC 124 ms
86,232 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=}", flush=True)
            printe(f"{self.__ans}", flush=True)
        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, flush=True)
        if self.__is_submit:
            return
        if self.__ans == password:
            printe("Correct", flush=True)
        else:
            printe("Incorrect", flush=True)


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


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