Skip to content

数据生成器规范

Tuack-NG 使用 C++ 程序作为数据生成器,驱动测试数据的自动生成。

生成器位置

使用 tuack-ng dmk 以调用生成器生成数据。

推荐按照以下方式在题目目录中组织生成器:

txt
myoi/day1/aplusb/
├── conf.json
├── gen/
│   ├── gen.cpp        # 数据生成器
│   └── gen_sample.cpp # 样例数据生成器
└── ...

配置文件

在题目的 conf.json 中,通过 generator 字段配置生成器:

json
{
  "generator": {
    "data": {
      "gen": "gen/gen.cpp",
      "deps": ["gen/testlib.h"]
    },
    "sample": {
      "gen": "gen/gen_sample.cpp",
      "deps": []
    }
  }
}
  • generator.data:正式测试数据的生成器配置
  • generator.sample:样例数据的生成器配置(可选)

如果 generator.sample 未配置,dmk sample 会回退使用 generator.data

字段类型说明
genstring生成器源文件路径(相对题目目录)
depsstring[]依赖文件列表,当这些文件发生变化时会重新编译生成器
validateboolean?生成输入后是否用 Validator 校验,默认 false,详见 校验配置

输入校验

如果配置了 Validator(见 校验配置),可以在生成输入后自动校验其合法性。

通过 generator.data.validate(或 generator.sample.validate)开启:

json
{
  "generator": {
    "data": {
      "gen": "gen/gen.cpp",
      "deps": [],
      "validate": true
    }
  }
}

校验失败时,该数据点的输入会标记为 FAIL

也可以在命令行临时覆盖:tuack-ng dmk data gen --validate 强制开启,--validate=false 强制关闭。

编写规范

使用 Testlib

强烈建议使用 Testlib 编写生成器,以获得跨平台一致的随机数和健壮的命令行参数解析。

cpp
#include "testlib.h"

int main(int argc, char* argv[]) {
  registerGen(argc, argv, 1);         // 注册生成器

  rnd.setSeed(opt<uint64_t>("seed")); // 设置随机数种子
  int n = opt<int>("n");              // 读取命名参数
  int m = rnd.next(1, 1000);          // 生成随机数

  // ...
  return 0;
}

参数传递

生成器参数可以通过 conf.json 中数据点的 args 字段配置,见 配置

Tuack-NG 会将 args 中的键值对作为 --key=value 命令行参数传递给生成器。同时,Tuack-NG 会传入 --seed=<一个 64 位无符号整数>,你必须使用它作为生成器的随机数种子

编译参数

生成器使用 -O2 -std=c++17 编译参数进行编译,目前你无法自行修改。

示例

cpp
// gen/gen.cpp
#include "testlib.h"
#include <iostream>

int main(int argc, char* argv[]) {
  registerGen(argc, argv, 1);

  int n = opt<int>("n");
  int q = opt<int>("q");

  std::cout << n << " " << q << "\n";
  for (int i = 0; i < n; i++) {
    std::cout << rnd.next(1, 1000000000) << " \n"[i == n - 1];
  }
  // ...
  return 0;
}