テストケースバリデーションの書き方

Latest Author maimai /Date 2021-06-29 22:25:37 / Views 2126
2 (Favした一覧ページはユーザーページから)

テストケースバリデーションの書き方

テストケースバリデーションとは

入力制約を満たさないテストケースが含まれているかどうか、プログラムを利用して自動的に判定する機能です。

バリデータの書き方

  • 競技プログラミング同様、標準入力からテストケースが与えられます。
  • スペシャルジャッジの書き方同様、そのテストケースに不備があるならば、0以外の終了コードで終了します。不備がなければ、0の終了コードで終了します。
  • 標準エラー出力に情報を出力すると、後で確認出来ます。
  • C++の場合、testlib が使えます。testlibを使うことで、余分な半角スペースや改行の不備等を簡単に発見できます。
  • コンパイルエラーが表示されないので、オンライン実行を使うと良いです。

実装例

以下のような入力制約を考えます。

$N$
$M_1$ $a_{1,1}$ $\ldots$ $a_{1,M_1}$
$\vdots$
$M_N$ $a_{N,1}$ $\ldots$ $a_{N,M_N}$

$1 \le N \le 4000$
$1 \le M_i \le 4000$
$1 \le a_{i,j} \le 4000$

$\sum_{i=1\ldots N}{M_i} \le 4000$
すべて整数

testlib (C++14)を使って実装すると、以下のようになります。
#include <bits/stdc++.h>
#include "testlib.h"

using namespace std;
using ll = long long;

int main(int argc, char** argv) {
  registerValidation(argc, argv);

  ll n = inf.readLong(1ll, 4000ll);
  inf.readEoln();

  ll mtotal = 0;

  for (ll i = 0; i < n; ++i) {

    ll m = inf.readLong(1ll, 4000ll);
    mtotal += m;

    for (ll j = 0; j < m; ++j) {
      inf.readSpace();

      inf.readLong(1ll, 4000ll);
    }

    inf.readEoln();
  }
  
  assert(mtotal <= 4000);

  inf.readEof();
  return 0;
}
正規表現(Ruby)を使った実装例です
line1 = gets.chomp!
abort "line1" unless line1 =~ /^\d+$/

n = line1.to_i
abort "n" unless 1 <= n && n <= 4000

mtotal = 0
n.times do |i|
  linei = gets.chomp!
  abort "line#{i}" unless linei =~ /^\d+( \d+)*$/

  m, *aa = linei.split.map(&:to_i)
  abort "m#{i}" unless 1 <= m && m <= 4000
  mtotal += m

  aa.each do |a|
    abort "a#{i}" unless 1 <= a && a <= 4000
  end
  abort "aa.size" unless aa.size == m

end

abort "mtotal" unless mtotal <= 4000
abort "too many lines" unless !gets