You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何设计Codeforces交互式评测器?我的实现为何陷入死循环?

交互式题目评测器设计问题及排查

问题背景

在Codeforces上接触到交互式题目《1. Guess the Number》,已写出通过官方评测的正确解法,现在尝试编写本地评测器(grader/interactor)用于测试,但运行时出现异常。

现有代码

正确解法(1_Guess_the_Number.py)

#!/usr/bin/env python3

l, r = 1, 1000000
while l != r:
    mid = (l + r + 1) // 2
    print(mid, flush=True)
    response = input()
    if response == "<":
        r = mid - 1
    else:
        l = mid

print("!", l)

自制评测器(grader.py)

#!/usr/bin/env python3

import sys

INP = 12


def interactor(n):
    if n > INP:
        return "<"
    return ">="


while True:
    guess = input()
    if guess.startswith("!"):
        print(int(guess.split()[1]) == INP, flush=True)
        sys.exit()
    print(interactor(int(guess)), flush=True)

运行异常

执行命令 ./1_Guess_the_Number.py | ./grader.py 时,终端陷入无限循环,仅输出 <,程序无法正常完成交互流程。

问题排查与解决

核心问题:单向管道无法满足双向通信需求

| 是单向管道,仅能将前一个程序的输出传递给后一个程序的输入,但交互式题目需要双向通信(解法程序发送猜测 → 评测器返回结果 → 解法程序接收结果并继续)。单向管道下,评测器的输出直接打印到终端,解法程序无法读取到反馈,导致解法程序卡在 input() 等待输入,评测器则卡在 input() 等待解法程序的下一个猜测,形成死锁。

解决方案

方法1:用Python subprocess实现双向通信

编写测试脚本 test.py,通过subprocess模块管理解法程序的输入输出,模拟评测逻辑:

#!/usr/bin/env python3
import subprocess

# 启动解法程序,创建双向管道连接
proc = subprocess.Popen(
    ['./1_Guess_the_Number.py'],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    text=True
)

TARGET = 12

while True:
    # 读取解法程序的猜测
    guess_line = proc.stdout.readline().strip()
    if not guess_line:
        break

    if guess_line.startswith("!"):
        # 验证最终答案
        final_ans = int(guess_line.split()[1])
        print(f"测试结果: {'正确' if final_ans == TARGET else '错误'}")
        proc.stdin.close()
        proc.wait()
        break

    # 生成评测反馈
    guess_num = int(guess_line)
    resp = "<" if guess_num > TARGET else ">="
    # 将反馈发送给解法程序
    proc.stdin.write(f"{resp}\n")
    proc.stdin.flush()

运行 ./test.py 即可完成双向交互测试。

方法2:用命名管道(FIFO)实现双向通信

通过创建两个命名管道分别处理两个方向的数据流:

# 创建命名管道
mkfifo pipe1 pipe2
# 后台启动解法程序,从pipe2读反馈,向pipe1发猜测
./1_Guess_the_Number.py < pipe2 > pipe1 &
# 启动评测器,从pipe1读猜测,向pipe2发反馈
./grader.py < pipe1 > pipe2
# 测试完成后删除管道
rm pipe1 pipe2

其他实现思路

可以将评测逻辑直接整合到解法程序中,添加测试模式,无需单独编写评测器:
修改后的解法程序(支持本地测试):

#!/usr/bin/env python3
import sys

def simulate_feedback(guess, target):
    return "<" if guess > target else ">="

def main():
    # 测试模式:传入--test参数指定目标数
    if len(sys.argv) > 1 and sys.argv[1] == "--test":
        target = int(sys.argv[2]) if len(sys.argv) > 2 else 12
        l, r = 1, 1000000
        while l != r:
            mid = (l + r + 1) // 2
            print(f"猜测: {mid}")
            resp = simulate_feedback(mid, target)
            print(f"反馈: {resp}")
            if resp == "<":
                r = mid - 1
            else:
                l = mid
        print(f"! {l}")
        print(f"结果: {'正确' if l == target else '错误'}")
    else:
        # 正常提交模式
        l, r = 1, 1000000
        while l != r:
            mid = (l + r + 1) // 2
            print(mid, flush=True)
            response = input()
            if response == "<":
                r = mid - 1
            else:
                l = mid
        print("!", l)

if __name__ == "__main__":
    main()

运行 ./1_Guess_the_Number.py --test 12 即可直接本地测试,无需额外启动评测器进程。

内容的提问来源于stack exchange,提问作者sgalpha01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:52:14