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

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

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

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

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

バリデータの書き方

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

実装例

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

NN
M1M_1 a1,1a_{1,1} \ldots a1,M1a_{1,M_1}
\vdots
MNM_N aN,1a_{N,1} \ldots aN,MNa_{N,M_N}

1N40001 \le N \le 4000
1Mi40001 \le M_i \le 4000
1ai,j40001 \le a_{i,j} \le 4000

i=1NMi4000\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