upgrade to python3;add some validator examples

This commit is contained in:
2025-10-11 12:33:24 +08:00
parent 65632f0e60
commit 487c041148
25 changed files with 1492 additions and 317 deletions

View File

@@ -0,0 +1,295 @@
# BitOJ 自定义验证程序完整指南
## 概述
BitOJ系统支持4种判题方式
1. **字符串精确比较** - 逐字符对比输出
2. **字符串容错比较** - 允许格式错误(PE),主要比较数字内容
3. **文件MD5校验** - 比较文件大小和MD5值
4. **自定义验证程序** - 编写专门的验证逻辑
本文档重点介绍第4种方式自定义验证程序的编写和使用。
## 自定义验证程序原理
### 工作流程
1. 系统执行用户提交的代码
2. 将输入、期望输出、实际输出传递给验证程序
3. 验证程序分析这些文件并返回判题结果
4. 系统根据返回结果确定最终评分
### 参数说明
验证程序接收以下参数:
- `argv[1]`: 标准输入文件路径
- `argv[2]`: 期望输出文件路径
- `argv[3]`: 用户程序输出文件路径
### 返回值
验证程序必须输出以下结果之一:
- `AC` - Accepted答案正确
- `PE` - Presentation Error格式错误
- `WA` - Wrong Answer答案错误
## 实际示例
### 1. 浮点数误差比较 (C++)
**适用场景**: 计算几何、数值计算等需要浮点数比较的题目
```cpp
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
const double EPS = 1e-9;
int main(int argc, char* argv[]) {
ifstream expected(argv[2]); // 标准答案
ifstream result(argv[3]); // 用户输出
double exp_val, res_val;
if (!(expected >> exp_val) || !(result >> res_val)) {
cout << "WA" << endl;
return 0;
}
if (fabs(exp_val - res_val) <= EPS) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
return 0;
}
```
### 2. 多解答案验证 (Python)
**适用场景**: 排序题、图论路径题等有多种正确答案的题目
```python
#!/usr/bin/env python
import sys
def main():
try:
with open(sys.argv[2], 'r') as f:
expected = f.read().strip()
with open(sys.argv[3], 'r') as f:
result = f.read().strip()
# 解析数字并排序比较
expected_nums = sorted(map(int, expected.split()))
result_nums = sorted(map(int, result.split()))
if expected_nums == result_nums:
print("AC")
else:
print("WA")
except:
print("WA")
if __name__ == "__main__":
main()
```
### 3. 输出格式验证 (Java)
**适用场景**: 需要严格输出格式的竞赛题目
```java
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
public class StringFormatValidator {
public static void main(String[] args) {
try {
Scanner result = new Scanner(new File(args[2]));
int lineNum = 1;
while (result.hasNextLine()) {
String line = result.nextLine().trim();
// 检查格式Case #X: Y
Pattern pattern = Pattern.compile("^Case #" + lineNum + ": \\d+$");
if (!pattern.matcher(line).matches()) {
System.out.println("PE");
return;
}
lineNum++;
}
System.out.println("AC");
} catch (Exception e) {
System.out.println("WA");
}
}
}
```
## 在BitOJ中配置自定义验证程序
### 代码配置示例
```python
from judgescript import ExternalJudge
# 创建自定义验证程序
validator = ExternalJudge(
problemid='P1001', # 题目ID
vlang='gcc-3.3', # 验证程序语言
vcode=validator_code # 验证程序源代码
)
# 在测试过程中调用
result = validator.judge(
sid='S123', # 提交ID
tid='T001', # 测试用例ID
tin='/path/to/input.txt', # 输入文件
tout='/path/to/output.txt', # 期望输出
result='/path/to/result.txt', # 实际输出
errfile='/path/to/error.txt' # 错误输出
)
```
### 支持的编程语言
| 语言 | 标识符 | 说明 |
|------|--------|------|
| C | gcc-3.3 | 适合高性能验证 |
| C++ | g++-3.3 | 支持STL容器 |
| Java | java-1.6 | 强类型安全 |
| Python | python-2.5 | 快速开发 |
| Pascal | fpc-2.2 | 简单逻辑 |
## 最佳实践
### 1. 错误处理
```cpp
// 文件读取失败处理
if (!input_file.is_open()) {
cout << "WA" << endl;
return 0;
}
// 数据解析失败处理
try {
value = stod(line);
} catch (const exception& e) {
cout << "WA" << endl;
return 0;
}
```
### 2. 性能优化
- 使用适当的数据结构
- 避免不必要的字符串操作
- 合理设置缓冲区大小
- 注意内存使用限制
### 3. 安全考虑
- 验证输入参数数量
- 处理异常文件路径
- 限制递归深度
- 避免无限循环
### 4. 可维护性
- 添加清晰的注释
- 使用有意义的变量名
- 模块化验证逻辑
- 提供调试输出选项
## 常见应用场景
### 1. 数值计算题
- 浮点数精度比较
- 矩阵运算结果验证
- 统计数值的近似比较
### 2. 图论算法题
- 最短路径验证(允许多条等长路径)
- 最小生成树验证(权重相等即可)
- 图遍历结果验证
### 3. 字符串处理题
- 忽略大小写比较
- 忽略空白字符差异
- 正则表达式匹配
### 4. 组合数学题
- 排列组合结果验证
- 集合操作结果比较
- 数学证明步骤检查
### 5. 交互式题目
- 模拟交互过程
- 验证查询次数限制
- 检查答案正确性
## 调试技巧
### 1. 本地测试
```bash
# 编译验证程序
g++ -o validator validator.cpp
# 准备测试文件
echo "3.14159" > expected.txt
echo "3.14160" > result.txt
# 运行测试
./validator input.txt expected.txt result.txt
```
### 2. 日志输出
```cpp
#ifdef DEBUG
cerr << "Expected: " << exp_val << ", Got: " << res_val << endl;
cerr << "Difference: " << fabs(exp_val - res_val) << endl;
#endif
```
### 3. 边界情况测试
- 空输出文件
- 超大数值
- 特殊字符
- 格式错误的输入
## 故障排除
### 常见问题
1. **编译失败**
- 检查语言版本兼容性
- 确认头文件引用正确
- 验证语法错误
2. **运行超时**
- 优化算法复杂度
- 减少不必要的计算
- 检查是否有死循环
3. **内存不足**
- 减少内存分配
- 及时释放资源
- 使用流式处理
4. **判题结果异常**
- 验证输出格式
- 检查返回值规范
- 确认异常处理逻辑
## 总结
自定义验证程序是BitOJ系统最灵活的判题方式能够处理各种复杂的判题需求。通过合理设计验证逻辑可以支持
- 多解答案题目
- 浮点数精度要求
- 特殊输出格式
- 交互式评测
- 复杂的正确性检查
掌握自定义验证程序的编写技巧,能够大大扩展在线评测系统的应用范围,为各种类型的编程竞赛和教学需求提供支持。