とあるABC337にて
こんな問題が出てきました。
具体的な問題は実際に見てもらうとして、本題はこれがインタラクティブ問題だということです。
つまりコードテストにぶちこむだけでは合ってるかどうかすらわからない。これではペナりまくってしまう。
ですのでテスターをサクッと自作したいと思います
subprocessを使う
やばい、めんどい、使いたくない。
pipeとかを使えば行けるぽいですが、osレベルの話に関わってくるのでコンテスト中に作成するのは断念
pexpectを使う
subprocess以外に出てきたいい感じのやつです。
以下ここからサンプルコード
# This connects to the openbsd ftp site and
# downloads the recursive directory listing.
import pexpect
child = pexpect.spawn('ftp ftp.openbsd.org')
child.expect('Name .*: ')
child.sendline('anonymous')
child.expect('Password:')
child.sendline('noah@example.com')
child.expect('ftp> ')
child.sendline('lcd /tmp')
child.expect('ftp> ')
child.sendline('cd pub/OpenBSD')
child.expect('ftp> ')
child.sendline('get README')
child.expect('ftp> ')
child.sendline('bye')
単純で使いやすそうです。
そして以下が作ったテスターになります
import random
import pexpect
import time
def main(n):
p = pexpect.spawn('python3 e.py')
x = random.randint(1,n)
#print("n:",n)
p.sendline(str(n))
p.expect("\n")
m = p.before.decode(encoding='utf-8')
p.expect("\n")
m = p.before.decode(encoding='utf-8')
print("n:",n,"m:",m)
m = int(m)
result = ""
for i in range(m):
p.expect("\n")
s = p.before.decode(encoding='utf-8').split()
#print(f"{i+1}:",s)
s = list(map(int,s))[1:]
if x in s:
result+="1"
else:
result+="0"
p.sendline(result)
p.expect("\n")
s = p.before.decode(encoding='utf-8')
p.expect("\n")
s = p.before.decode(encoding='utf-8')
if int(s)!=int(x): #or not(2**m>n and 2**(m-1)<=n):
print("n:",n)
print("s:",s)
print("x:",x)
time.sleep(9999)
if __name__ == "__main__":
while True:
for i in range(2,101):
main(i)
注意点
-
どうやらWindowsで動かすのはめんどくさいらしい
Window上で動かすとどういうわけかエラーを吐く、Linuxなら上手くいくらしいのでWSLで代用 -
一部の入力は二回連続受け取らないといけないぽい
なんでだ?まぁこれで上手くいくので別に問題ない