結果

問題 No.2768 Password Crack
ユーザー ThetaTheta
提出日時 2024-07-12 18:31:26
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 245 ms / 2,000 ms
コード長 3,672 bytes
コンパイル時間 1,097 ms
コンパイル使用メモリ 82,048 KB
実行使用メモリ 96,600 KB
平均クエリ数 888.77
最終ジャッジ日時 2024-07-12 18:31:35
合計ジャッジ時間 8,389 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 97 ms
82,504 KB
testcase_01 AC 85 ms
82,008 KB
testcase_02 AC 245 ms
95,824 KB
testcase_03 AC 83 ms
82,776 KB
testcase_04 AC 201 ms
95,960 KB
testcase_05 AC 104 ms
84,184 KB
testcase_06 AC 223 ms
96,344 KB
testcase_07 AC 99 ms
84,312 KB
testcase_08 AC 111 ms
85,592 KB
testcase_09 AC 203 ms
95,832 KB
testcase_10 AC 212 ms
96,600 KB
testcase_11 AC 217 ms
95,832 KB
testcase_12 AC 222 ms
96,088 KB
testcase_13 AC 215 ms
96,088 KB
testcase_14 AC 206 ms
95,960 KB
testcase_15 AC 182 ms
95,064 KB
testcase_16 AC 220 ms
95,704 KB
testcase_17 AC 216 ms
96,216 KB
testcase_18 AC 221 ms
95,576 KB
testcase_19 AC 133 ms
90,328 KB
testcase_20 AC 127 ms
88,920 KB
testcase_21 AC 203 ms
96,088 KB
testcase_22 AC 173 ms
95,192 KB
testcase_23 AC 109 ms
84,568 KB
testcase_24 AC 140 ms
89,304 KB
testcase_25 AC 199 ms
95,704 KB
testcase_26 AC 132 ms
89,176 KB
testcase_27 AC 180 ms
95,320 KB
testcase_28 AC 111 ms
85,456 KB
testcase_29 AC 125 ms
86,872 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:
        assert N != -1 or (not is_submit)
        self.__is_submit = is_submit
        if is_submit or ans:
            self.__ans = ans
            self.N = N
        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)
        printe(is_valid, prev_correct_n)
        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