Custom checkers
Một số bài tập có thể có nhiều output đúng, vì vậy đôi lúc ta cần phải viết checker để kiểm tra xem output có đúng hay chưa.
1. Checker mặc định
VNOJ có hỗ trợ các checker mặc định của DMOJ, các bạn có thể xem ở đây
2. Custom Checker (Python)
Một checker
được viết bằng Python cần cài đặt một hàm như sau:
def check(process_output, judge_output, **kwargs):
# your code
Trong đó:
process_output
: output của bài nộpjudge_output
: đáp án
**kwargs
có thể chứa các biến sau:
submission_source
: source code của bài nộpjudge_input
: input của đề bàipoint_value
: điểm của test đang chấmcase_position
: thứ tự của testbatch
: batch của test case (với các bài chấm theo subtask), đại đa số các bài ta không cần quan tâm tới biến này.submission_language
: ngôn ngữ của bài nộpexecution_time
: thời gian chạy, tính bằng giây
Return
Hàm check
có 2 cách return:
- Return bằng True hoặc False, nếu đáp án đúng thì return True, ngược lại return False
- Return bằng
CheckerResult
, return bằng cách này thì có thể trả về được feedback cho người nộp. Cách dùng như sau:CheckerResult(passed, points_awarded)
. Trong đó:passed
là có giá trị True/False tùy vào kết quả có đúng hay không.points_awarded
: là số điểm nhận được với test đó.feedback
: thông tin đưa tới người nộp.
Ví dụ
Dưới đây là checker mẫu cho bài toán POST - A cộng B.
from dmoj.result import CheckerResult
def check(process_output, judge_output, judge_input, point_value, **kwargs):
# convert from bytes to texts
process_output = process_output.decode("ascii")
judge_output = judge_output.decode("ascii")
judge_input = judge_input.decode("ascii")
# read data as normal
a, b = judge_input.split(' ')
output_sum = int(process_output)
if a + b != output_sum:
return CheckerResult(False, 0, f"{a} + {b} != {output_sum}")
return CheckerResult(True, point_value, "Ok answer is correct")
3. Custom Checker (C++)
Để viết được C++ checker, ta cần viết một chương trình C++ nhận vào 3 tham số dòng lệnh theo thứ tự là input_file
, output_file
, answer_file
, tươn ứng với đường dẫn tới các file input, output, đáp án.
Return
Chương trình (hàm main) trả về các giá trị sau:
- 0 nếu AC (100% số điểm)
- 1 nếu WA (0 điểm)
- 7 nếu nhận được điểm thành phần. Khi đó cần in ra
stderr
một số thực trong đoạn[0, 1]
thể hiện tỷ lệ điểm. Lưu ý rằng điểm phải được in ra ở dòng đầu tiên củastderr
- Nếu chương trình trả về giá trị khác (exit code khác 0, hay run time error) thì bài nộp sẽ được 0 điểm (xem như WA).
Những thông tin được viết ra stdout
sẽ được in ra màn hình cho người nộp bài (feedback), nhưng thông tin này chỉ hiển thị được khoản 20 ký tự.
Nếu muốn người dùng xem được nhiều feedback hơn, thì in feedback vào stderr (lưu ý in sau khi in điểm ở dòng đầu tiên).
Ví dụ:
Chương trình sau dùng để chấm bài toán: Cho ~n~ là một số nguyên dương. In ra hai số tự nhiên ~a~, ~b~ sao cho ~a + b = n~.
Nếu in ra ~a + b = n~ và ~a, b \ge 0~ thì được ~100\%~ số điểm, nếu ~a + b = n~ nhưng một trong 2 số ~a, b~ âm thì được ~50\%~ số điểm.
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char** argv) {
ifstream inp(argv[1]);
ifstream out(argv[2]);
ifstream ans(argv[3]);
int n, a, b, c, d;
inp >> n;
out >> a >> b;
ans >> c >> d;
if (a + b == c + d) {
cout << a << " + " << b << " = " << c << " + " << d << endl;
if (a >= 0 && b >= 0) {
cerr << "This line will be show to the contestants as a extended feedback";
return 0; // AC
}
else {
cerr << 0.5 << '
'; // in ra điểm ở dòng đầu tiên
cerr << "Thís line will be show to the contestants as a extended feedback";
return 7; // PARTIAL
}
}
else {
cout << "a + b = " << a + b << " != " << n << endl;
return 1; // WA
}
}
VNOJ cũng hộ trợ các checker được viết bằng testlib.h, tuy nhiên hiện tại chỉ có thể chấm các bài không phải interactive.
Đây là checker được viết bằng testlib.h
cho bài toán trên:
#include "testlib.h"
using namespace std;
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
int n = inf.readInt();
int a = ouf.readInt();
int b = ouf.readInt();
ensuref(a + b == n, "%d + %d != %d", a, b, n);
if (a < 0) {
quitf(_points, "0.5
a = %d < 0", a);
}
if (b < 0) {
quitf(_points, "0.5
b = %d < 0", a);
}
quitf(_ok, "%d + %d = %d", a, b, n);
}