Привет, CodeForces!
Основная информация
Я написал генератор тестов на C++. Он очень прост, состоит из двух функций: генерация случайного числа в промежутке от $$$a$$$ до $$$b$$$, так, чтобы это случайное число было кратно $$$k$$$ (функция: genint(a, b, k, add)
, где add
— "добавлять" ли в тест это число) и генерация случайной строки. Тут надо расписать:
- Генерирует строку случайной длины в промежутке от $$$a$$$ до $$$b$$$, так, чтобы она была кратна $$$k$$$.
- Состоящую из заданных символов. Задавать символы можно двумя способами: написать промежуток
("a-f", "x-z")
или конкретный символ ("m", "o")
. Функция: genstr(a, b, k, pattern, add)
, где pattern
— массив заданных промежутков или конкретных символов.
Код#include <bits/stdc++.h>
using namespace std;
#define int long long
string test = "";
int genint(int a, int b, int k, bool add) {
if (a == b) {
if (add) test += to_string(a);
return a;
}
int ans = (rand() % (b / k - a / k) + (a / k + (a % k != 0))) * k;
if (add) test += to_string(ans);
return ans;
}
string genstr(int a, int b, int k, vector <string> p, bool add) {
int l = genint(a, b, k, 0);
vector <char> symbols;
for (int i = 0; i < p.size(); i++) {
if (p[i].size() == 1) {
symbols.push_back(p[i][0]);
} else {
for (char j = p[i][0]; j <= p[i][2]; j++) {
symbols.push_back(j);
}
}
}
string ans = "";
for (int i = 0; i < l; i++) {
ans += symbols[genint(0, symbols.size(), 1, 0)];
}
if (add) test += ans;
return ans;
}
signed main() {
srand(time(NULL));
// generating test
// ---------------
freopen("test", "w", stdout);
cout << test;
}
Применения
Есть такая задача: Вам дана строка состоящая из $$$n (n \le 10^5)$$$ символов. Вам требуется процент содержания (с точностью до $$$10^{-5}$$$) каждого символа, который есть в строке. Пример ввода и вывода:
ПримерВвод
1
5
abcde
Вывод
a 20
b 20
c 20
d 20
e 20
Ввод
1
5
abcda
Вывод
a 40
b 20
c 20
d 20
Вам требуется обработать $$$t$$$ наборов входных данных
Для нас, участников соревнования, эта задача очень проста, но для составителей надо написать такие тесты, в которых будут и крайние и обычные случаи. Писать это вручную — плохой вариант. Тем более, что $$$n \le 10^5$$$
С помощью моего генератора можно сделать хорошие тесты в несколько строк:
const int mintestcases = 5;
const int maxtestcases = 8;
const int minlength = 10;
const int maxlength = 20;
for (int i = 0; i < 5; i++) { // генерирует 5 тестов
string test = "";
int t = genint(mintestcases, maxtestcases, 1, true);
test += '\n';
for (int j = 0; j < t; j++) {
int n = genint(minlength, maxlength, 5, true);
test += '\n';
genstr(n, n, 1, {"a-z"}, true);
test += '\n';
}
}
ТестыТест 1
7
15
qghumeaylnlfdxf
10
rcvscxggbw
10
fnqduxwfnf
10
zvsrtkjpre
15
ggxrpnrvystmwcy
10
yycqpevike
15
fmznimkkasvwsre
Тест 2
6
15
kycxfxtlsgypsfa
15
pooefxzbcoejuvp
15
aboygpoeylfpbnp
15
jvrvipyamyehwqn
10
rqpmxujjlo
10
vaowuxwhms
Тест 3
6
10
bxcoksfzkv
10
txdknlyjyh
15
ixjswnkkufnuxxz
15
zbmnmgqooketlyh
15
koaugzqrcddiute
10
ojwayyzpvs
Тест 4
5
10
psajlfvgub
15
aaovlzylntrkdcp
10
srtesjwhdi
15
cobzcnfwlqijtvd
10
vxhrcbldvg
Тест 5
7
15
wgbusbmborxtlhc
10
mpxohgmgnk
10
ufdxotogbg
15
peyanfetcukepzs
15
kljugggekjdqzje
15
pevqgxiepjsrdzj
10
zujllchhbf
Чтобы сделать большие тесты надо увеличить значения mintestcases
, maxtestcases
, minlength
, maxlength
. Для претестов можно взять по 1-2 тесту каждого "размера".
Можно генерировать строки состоящие из заглавных букв: genstr(10, 20, 5, {"A-D"}, true)
, результат: DCABACCCABBBDBD
Можно и сгенерировать строку состоящую из строчных и заглавных букв: genstr(10, 20, 5, {"A-D", "a-d"}, true)
, результат: DcaBaccCABBBDBD
Заключение
Этот генератор подойдет и для стресс тестирования. Генерировать тесты в задаче обычно не очень сложно. Подойдет он и для взломов. Можно очень легко сгенерировать "максимальный" тест.
Всем удачных раундов и высокого рейтинга, пока!