競プロインタラクティブ問題のローカルテスト

インタラクティブ形式の問題とは、入力が最初の1回きりではなく、 こちらの質問(出力)に従ってジャッジが回答となる新たな入力を与えるのを繰り返し、 その情報を元に隠された何かを突き止めるタイプの問題。

こういう形式は、提出前に正しく動作するかテストがしにくい。 また最大ケースに対してクエリ数がどれくらいになるかも、ちゃんと調べたい。

ジャッジ側のプログラムは自分で書くしかないが、それが比較的簡単に書けるなら、
Pythonではたとえば以下のように書くと、提出コードとジャッジ側の応答をシミュレートし、その履歴が得られる。

クエリを「? XXX」、解答を「! XXX」で送るような問題に対する実装例とする。

動作や諸注意

まず実行すると、judge() が呼ばれる。
judge() では自身をsubprocessで起動する。 ここで起動した方は judge() には進まず提出コードの方が実行されるよう、コマンドライン引数などで切り分ける。

プロセスを開始する Popen() の引数を stdin=PIPE, stdout=PIPE とすることにより、プロセス同士の対話が可能になる。
入出力のやりとりはstring型でなくbytes型なので、ジャッジ側が送ったり受け取ったりする文字列には decode, encode が必要となる。

競プロではまずascii文字しか使わないので、デコードに用いる文字コードは utf8ascii でよい。
(AtCoderではデフォルト文字コードが utf-8 なので無指定でもよいが、Codeforcesだと未定義なのでちゃんと指定しないとエラーになる)

また末尾の改行も、明示的に付与しないと提出コード側が入力待ちのまま動かなくなる。忘れないよう注意。

実装例


def judge():
    import sys
    import subprocess
    
    sin = '3 1 4 1 5\n'  # 最初の入力
    ans = 'TheAnswerOfSampleCase'  # 隠された答え
    query_count = 0  # クエリ回数カウント
    
    encoding = 'utf-8'
    
    with subprocess.Popen([sys.executable, __file__, 'DUMMY'],
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE) as p:
        
        # はじめに入力を与える処理
        p.stdin.write(sin.encode(encoding))
        p.flush()
        
        while True:
            query = p.stdout.readline().decode(encoding).strip()
            print(query)
            
            if query[0] == '?':
                # クエリへの返答を計算する処理
                response = 'hogehoge'
                
                print(response)
                p.stdin.write(f'{response}\n'.encode(encoding))
                p.stdin.flush()
                query_count += 1
                
            elif query[0] == '!':
                # 解答があっているかチェックする処理
                
                print(query[2:], ans, query[2:] == ans)
                print(query_count)
                break
            else:
                pass

# ↓提出時はコメントアウト↓
import sys

if len(sys.argv) == 1:
    judge()
    exit()

# ↓提出コード↓
# ...

Anacondaやvenvなど仮想環境のpythonを使いたい場合、subprocessからactivateするのはどうするんだろう。

本WebサイトはcookieをPHPのセッション識別および左欄目次の開閉状況記憶のために使用しています。同意できる方のみご覧ください。More information about cookies
programming_algorithm/python_tips/interactive.txt · 最終更新: 2020/09/18 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0