Hướng dẫn sử dụng Custom Checker trên FPTOJ
1. Giới thiệu về Custom Checker
Custom Checker là một đoạn mã Python hoặc C++ được sử dụng để kiểm tra đầu ra của bài làm một cách linh hoạt hơn. Nó đặc biệt hữu ích cho các bài toán có nhiều đầu ra đúng hoặc cần tính điểm dựa trên độ chính xác.
Mặc định, nếu không chỉ định checker, FPTOJ sẽ sử dụng standard
checker, tức là so sánh đầu ra của bài làm với đầu ra của test case theo từng dòng, bỏ qua khoảng trắng dư thừa.
2. Cách khai báo Checker trong init.yml
Trong file init.yml
, bạn có thể chỉ định checker bằng cách thêm trường checker
:
checker:
name: <tên checker>
args: {}
Hoặc nếu không cần truyền tham số, có thể khai báo đơn giản:
checker: <tên checker>
3. Các loại Checker có sẵn trên DMOJ
3.1. standard
Checker mặc định, kiểm tra đầu ra chính xác theo từng dòng, bỏ qua khoảng trắng dư thừa.
3.2. easy
So sánh đầu ra bất kể khoảng trắng và chữ hoa/thường. Kiểm tra số lần xuất hiện của từng ký tự.
3.3. floats
Dùng để so sánh số thực, hỗ trợ sai số dấu chấm động:
precision
: độ chính xác (mặc định là 6, tương đương (10^{-6})).error_mode
: cách tính sai số (default
,relative
,absolute
).
Ví dụ:
checker:
name: floats
args:
precision: 8
error_mode: relative
3.4. identical
Kiểm tra đầu ra giống hệt nhau kể cả khoảng trắng. Có thể tùy chọn pe_allowed
để cho phép cảnh báo Presentation Error.
3.5. linecount
Kiểm tra từng dòng, đánh dấu ✓ nếu đúng, ✗ nếu sai. Có thể bật/tắt phản hồi chi tiết qua feedback
.
3.6. sorted
Kiểm tra đầu ra đúng nhưng không quan trọng thứ tự:
split_on: lines
(mặc định) – kiểm tra thứ tự dòng.split_on: whitespace
– kiểm tra thứ tự token.
3.7. unordered
Alias của sorted
với split_on: whitespace
.
4. Tạo Custom Checker bằng Python
Nếu cần một checker tùy chỉnh, bạn có thể tạo một script Python với một hàm check()
như sau:
from dmoj.result import CheckerResult
def check(process_output, judge_output, **kwargs):
if process_output.strip() == judge_output.strip():
return CheckerResult(True, 1.0, "Đáp án chính xác!")
else:
return CheckerResult(False, 0.0, "Sai đáp án!")
Các tham số kwargs
hữu ích:
submission_source
: Mã nguồn của bài nộp.judge_input
: Đầu vào của test case.point_value
: Điểm tối đa của test case.execution_time
: Thời gian chạy của bài nộp.problem_id
: ID của bài toán.
Nếu muốn chạy checker ngay cả khi bài nộp bị lỗi biên dịch hoặc thời gian chạy quá giới hạn, thêm dòng sau:
check.run_on_error = True
5. Checker sử dụng ngôn ngữ C++ với testlib.h
Nếu cần hiệu suất cao hoặc kiểm tra đầu ra phức tạp hơn, có thể sử dụng thư viện testlib.h
.
5.1. Cấu trúc cơ bản của checker C++ với testlib.h
#include <bits/stdc++.h>
#include "testlib.h"
using namespace std;
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
int n = inf.readInt(); // Đọc dữ liệu đầu vào
int a = ouf.readInt(); // Đọc đáp án của thí sinh
int b = ouf.readInt(); // Đọc đáp án của thí sinh
ensuref(a + b == n, "%d + %d != %d", a, b, n); // Kiểm tra điều kiện
quitf(_ok, "%d + %d = %d", a, b, n);
}
5.2. Giải thích các luồng dữ liệu trong testlib.h
inf
: Đọc dữ liệu đầu vào.ouf
: Đọc đầu ra của thí sinh.ans
: Đọc đáp án chuẩn.
Một số hàm hữu ích:
.readInt()
,.readLong()
,.readDouble()
: Đọc số nguyên/số thực..readString()
,.readLine()
: Đọc chuỗi hoặc dòng..seekEof()
,.seekEoln()
: Kiểm tra cuối file/cuối dòng.
5.3. Checker tính điểm từng phần
Nếu muốn chấm điểm từng phần, có thể sử dụng:
if (a < 0) {
quitf(_points, "0.5\n a = %d < 0", a);
}
Điều này sẽ cho 50% điểm nếu a
nhỏ hơn 0.
6. Kết luận
Custom Checker giúp bạn kiểm tra bài toán linh hoạt hơn, đặc biệt cho bài toán có nhiều đáp án đúng hoặc tính điểm theo độ chính xác. Bạn có thể sử dụng các checker có sẵn hoặc tự viết checker tùy chỉnh bằng Python hoặc C++ để tối ưu hiệu suất.