一个轻量级的本地数据生成器

· · 科技·工程

你是否有过这样的经历:出完一个题,写好了 std 和 maker,然后上讨论区求助“求生成数据模板”……

你是否有过这样的经历:出了一道图论题,图要卡掉 SPFA。用 C++ 写了 114514 小时……

如果你有以上困扰的话,那么欢迎使用 KittenGen

KittenGen 是什么

一个基于 Python3 的 Flask 框架搭建的本地化数据生成器。在运行时,它将本机作为服务器提供 web 服务。

之前我发布过文章,写的是 KittenGen1.0 版本。这个版本的 KittenGen 在我拿到机房用以后还发现了一些问题,比如 32 位电脑编译命令不对,python 版本过旧,均已在 KittenGen2.0 版本修复。

在评论区有大佬指出 HydroOJ 也有自动造数据功能。但经本人实测,这个造数据跑的时间太长会 TLE,输出太多还会 OLE,总之不好用。但是在本地跑就没有这种问题。

如何使用 KittenGen

首先你要有一个 Python3 环境,下载好 pip。可以直接去官网下载。

打开 cmd,输入:

pip install -U KittenGen

上述操作可能会比较慢,推荐使用清华镜像源:

pip install -U KittenGen -i https://pypi.tuna.tsinghua.edu.cn/simple

如果顺利的话,你就会看到下面这样的提示信息:

下载完成后,输入:

python -m KittenGen

如果运行成功,控制台信息如图:

其中 http://127.0.0.1:2025 就是这个服务的网址了。打开它:

就可以看到一个界面了。从上到下有这么几个板块:

标准程序

就是放自己的 std 的。无需 freopen。

数据生成器

支持 Python / C++ 两种语言。对于 Python,内置了洛谷的 CYaRon 库,可以方便地造图、树等数据。

数据配置

第一个输入框是指定数据组数的,第二个指定数据前缀名,比如 game1.in 什么的。

C++ 编译命令设置

G++ 路径就是选择自己使用的编译器的位置。如果你的 g++ 没有添加到环境变量中需要手动输入。下面这个编译选项是后面跟的东西。“64 位编译选项”是本人电脑用的选项,“32 位编译选项”是本人机房电脑的选项,你也可以自定义选项。

最后下面有个按钮“生成数据”,点击以后网页会卡住。此时看看控制台,会有进度显示:

等到数据生成完毕后,会发送一个 .zip 文件,里面装着的就是全部数据点了。

至于 Python / C++ 生成器怎么用,文档里已经写好了。下面给出文档中的代码。

::::info[一个单点修改,区间查询的数据结构题(Python)]

# 测试点规模配置
N = [0, 100, 2000, 100000, 100000, 200000, 200000, 300000, 400000, 500000, 500000]
Q = [0, 100, 2000, 100000, 100000, 200000, 200000, 300000, 400000, 500000, 500000]
E9 = 10 ** 9

# 根据测试点编号获取规模
n, q = N[num], Q[num]
print(n, q)

# 生成n个随机数作为初始数组
for i in range(n):
    print(randint(-E9, E9), end=' ')
print()

# 生成q个操作
for i in range(q):
    opt = choice([1, 2])  # 随机选择操作类型
    l = randint(1, n)     # 随机左端点

    if opt == 1:
        # 单点修改操作
        print(opt, l, randint(-E9, E9))
    else:
        # 区间查询操作
        r = randint(1, n)
        if l > r:
            l, r = r, l
        print(opt, l, r)

::::

::::info[单源最短路模板题(Python)]

# 测试点规模配置
N = [0, 100, 2000, 100000, 100000, 200000, 200000, 300000, 400000, 500000, 500000]
M = [0, 100, 2000, 100000, 100000, 200000, 200000, 300000, 400000, 500000, 500000]
E9 = 10 ** 9

n = N[num]   # 点数
m = M[num]   # 边数
s = randint(1, n)   # 随机选取源点
print(n, m, s)
graph = cyaron.Graph.graph(n, m, weight_limit=E9)   # 生成一个n点,m边的随机图,边权限制为1e9
print(graph.to_str())   # 输出无向图,默认以一行一组u v w的形式输出

::::

::::info[一个单点修改,区间查询的数据结构题(C++)]

#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int randint(int l, int r) {
    return uniform_int_distribution<int>(l, r)(rng);
}

// 测试点规模配置
const int N[] = {0, 100, 2000, 100000, 100000, 200000, 200000, 300000, 400000, 500000, 500000};
const int Q[] = {0, 100, 2000, 100000, 100000, 200000, 200000, 300000, 400000, 500000, 500000};
const int E9 = 1e9;
int num;

int main() {
    // 关闭同步加速输出
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);

    // 根据测试点编号获取规模
    cin >> num;
    int n = N[num];
    int q = Q[num];
    cout << n << " " << q << "\n";

    // 生成n个随机数作为初始数组
    for (int i = 0; i < n; i++) {
        cout << randint(-E9, E9) << " ";
    }
    cout << "\n";

    // 生成q个操作
    while (q--) {
        int opt = randint(1, 2);  // 随机选择操作类型
        int l = randint(1, n);    // 随机左端点

        if (opt == 1) {
            // 单点修改操作
            cout << opt << " " << l << " " << randint(-E9, E9) << "\n";
        } else {
            // 区间查询操作
            int r = randint(1, n);
            if (l > r) swap(l, r);
            cout << opt << " " << l << " " << r << "\n";
        }
    }

    cout << flush;   // 注意刷新缓冲区
    return 0;
}

::::

结语

KittenGen 是一个非常好用的本机数据生成器。

但是 KittenGen 也会存在一些小 BUG,欢迎各位大佬指出,感激不尽!