Skip to content

Commit 80932ba

Browse files
Chilleesimonlindholm
authored andcommitted
Standardized fuzz tests for strings (#85)
1 parent 79520ad commit 80932ba

File tree

4 files changed

+114
-115
lines changed

4 files changed

+114
-115
lines changed

fuzz-tests/strings/KMP.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ int main() {
5454
test(s);
5555
});
5656
}
57+
cout<<"Tests passed!"<<endl;
5758
}

fuzz-tests/strings/MinRotation.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ int min_rotation2(string& v) {
2323
return j;
2424
}
2525

26-
int main2() {
27-
rep(it,0,10000) {
26+
void testPerf() {
27+
string s;
28+
rep(i,0,10000000)
29+
s += (char)(rand()%400000 < 2);
30+
cout << min_rotation(s) << endl;
31+
}
32+
33+
int main() {
34+
rep(it,0,1000000) {
2835
int n = rand() % 10;
2936
string v;
3037
rep(i,0,n) v += (char)(rand() % 3);
@@ -35,12 +42,5 @@ int main2() {
3542
assert(min_rotation(v) == 0);
3643
assert(min_rotation2(v) == 0);
3744
}
38-
return 0;
39-
}
40-
41-
int main() {
42-
string s;
43-
rep(i,0,10000000)
44-
s += (char)(rand()%400000 < 2);
45-
cout << min_rotation(s) << endl;
45+
cout<<"Tests passed!"<<endl;
4646
}

fuzz-tests/strings/SuffixArray.cpp

Lines changed: 101 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ typedef vector<int> vi;
1313
#include "../../content/strings/SuffixArray.h"
1414

1515
struct VecSuffixArray {
16-
vi sa, lcp;
16+
vi sa, lcp;
1717
VecSuffixArray(vi &s, int lim = 256) {
1818
int n = sz(s), k = 0;
1919
vi x(2 * n), y(2 * n), wv(n), ws(max(n, lim)), rank(n);
@@ -72,7 +72,7 @@ void test(const string& s, int alpha) {
7272

7373
if (suffixes != sa.sa) {
7474
cout << "sa fails for " << display(s) << ' ' << alpha << endl;
75-
exit(1);
75+
assert(suffixes == sa.sa);
7676
}
7777

7878
rep(i,0,sz(s)) {
@@ -85,7 +85,7 @@ void test(const string& s, int alpha) {
8585

8686
if (lcp != sa.lcp) {
8787
cout << "lcp fails for " << display(s) << ' ' << alpha << endl;
88-
exit(1);
88+
assert(lcp == sa.lcp);
8989
}
9090
}
9191

@@ -94,134 +94,131 @@ namespace old {
9494
typedef long long ll;
9595
typedef pair<ll, int> pli;
9696
void count_sort(vector<pli> &b, int bits) { // (optional)
97-
// this is just 3 times faster than stl sort for N=10^6
98-
int mask = (1 << bits) - 1;
99-
for (int it = 0; it < 2; it++) {
100-
int move = it * bits;
101-
vector<int> q(1 << bits), w((q).size() + 1);
102-
for (int i = 0; i < sz(b); i++)
103-
q[(b[i].first >> move) & mask]++;
104-
partial_sum(q.begin(), q.end(), w.begin() + 1);
105-
vector<pli> res(b.size());
106-
for (int i = 0; i < sz(b); i++)
107-
res[w[(b[i].first >> move) & mask]++] = b[i];
108-
swap(b, res);
109-
}
97+
// this is just 3 times faster than stl sort for N=10^6
98+
int mask = (1 << bits) - 1;
99+
for (int it = 0; it < 2; it++) {
100+
int move = it * bits;
101+
vector<int> q(1 << bits), w((q).size() + 1);
102+
for (int i = 0; i < sz(b); i++)
103+
q[(b[i].first >> move) & mask]++;
104+
partial_sum(q.begin(), q.end(), w.begin() + 1);
105+
vector<pli> res(b.size());
106+
for (int i = 0; i < sz(b); i++)
107+
res[w[(b[i].first >> move) & mask]++] = b[i];
108+
swap(b, res);
109+
}
110110
}
111111
struct SuffixArray {
112-
vector<int> a;
113-
string s;
114-
SuffixArray(const string &_s) : s(_s + '\0') {
115-
int N = sz(s);
116-
vector<pli> b(N);
117-
a.resize(N);
118-
for (int i = 0; i < N; i++) {
119-
b[i].first = s[i];
120-
b[i].second = i;
121-
}
112+
vector<int> a;
113+
string s;
114+
SuffixArray(const string &_s) : s(_s + '\0') {
115+
int N = sz(s);
116+
vector<pli> b(N);
117+
a.resize(N);
118+
for (int i = 0; i < N; i++) {
119+
b[i].first = s[i];
120+
b[i].second = i;
121+
}
122122

123-
int q = 8;
124-
while ((1 << q) < N)
125-
q++;
126-
for (int moc = 0;; moc++) {
127-
count_sort(b, q); // sort(all(b)) can be used as well
128-
a[b[0].second] = 0;
129-
for (int i = 1; i < N; i++)
130-
a[b[i].second] = a[b[i - 1].second] + (b[i - 1].first != b[i].first);
123+
int q = 8;
124+
while ((1 << q) < N)
125+
q++;
126+
for (int moc = 0;; moc++) {
127+
count_sort(b, q); // sort(all(b)) can be used as well
128+
a[b[0].second] = 0;
129+
for (int i = 1; i < N; i++)
130+
a[b[i].second] = a[b[i - 1].second] + (b[i - 1].first != b[i].first);
131131

132-
if ((1 << moc) >= N)
133-
break;
134-
for (int i = 0; i < N; i++) {
135-
b[i].first = (ll)a[i] << q;
136-
if (i + (1 << moc) < N)
137-
b[i].first += a[i + (1 << moc)];
138-
b[i].second = i;
139-
}
140-
}
141-
for (int i = 0; i < sz(a); i++)
142-
a[i] = b[i].second;
143-
}
144-
vector<int> lcp() {
145-
// longest common prefixes: res[i] = lcp(a[i],
146-
// a[i-1])
147-
int n = sz(a), h = 0;
148-
vector<int> inv(n), res(n);
149-
for (int i = 0; i < n; i++)
150-
inv[a[i]] = i;
151-
for (int i = 0; i < n; i++)
152-
if (inv[i] > 0) {
153-
int p0 = a[inv[i] - 1];
154-
while (s[i + h] == s[p0 + h])
155-
h++;
156-
res[inv[i]] = h;
157-
if (h > 0)
158-
h--;
159-
}
160-
return res;
161-
}
132+
if ((1 << moc) >= N)
133+
break;
134+
for (int i = 0; i < N; i++) {
135+
b[i].first = (ll)a[i] << q;
136+
if (i + (1 << moc) < N)
137+
b[i].first += a[i + (1 << moc)];
138+
b[i].second = i;
139+
}
140+
}
141+
for (int i = 0; i < sz(a); i++)
142+
a[i] = b[i].second;
143+
}
144+
vector<int> lcp() {
145+
// longest common prefixes: res[i] = lcp(a[i],
146+
// a[i-1])
147+
int n = sz(a), h = 0;
148+
vector<int> inv(n), res(n);
149+
for (int i = 0; i < n; i++)
150+
inv[a[i]] = i;
151+
for (int i = 0; i < n; i++)
152+
if (inv[i] > 0) {
153+
int p0 = a[inv[i] - 1];
154+
while (s[i + h] == s[p0 + h])
155+
h++;
156+
res[inv[i]] = h;
157+
if (h > 0)
158+
h--;
159+
}
160+
return res;
161+
}
162162
};
163163
} // namespace kactl
164164

165165
struct timeit {
166-
decltype(chrono::high_resolution_clock::now()) begin;
167-
const string label;
168-
timeit(string label = "???") : label(label) { begin = chrono::high_resolution_clock::now(); }
169-
~timeit() {
170-
auto end = chrono::high_resolution_clock::now();
171-
auto duration = chrono::duration_cast<chrono::milliseconds>(end - begin).count();
172-
cerr << duration << "ms elapsed [" << label << "]" << endl;
173-
}
166+
decltype(chrono::high_resolution_clock::now()) begin;
167+
const string label;
168+
timeit(string label = "???") : label(label) { begin = chrono::high_resolution_clock::now(); }
169+
~timeit() {
170+
auto end = chrono::high_resolution_clock::now();
171+
auto duration = chrono::duration_cast<chrono::milliseconds>(end - begin).count();
172+
cerr << duration << "ms elapsed [" << label << "]" << endl;
173+
}
174174
};
175175

176176
signed compare() {
177-
srand(0);
178-
vi vS;
179-
string S;
180-
for (int iter = 0; iter < 5; iter++) {
177+
srand(0);
178+
vi vS;
179+
string S;
180+
for (int iter = 0; iter < 5; iter++) {
181181

182-
for (int i = 0; i < MAXN; i++) {
183-
int t = rand() % 2;
184-
vS.push_back(t + 1);
185-
S.push_back((char)(t + 'a'));
186-
}
182+
for (int i = 0; i < MAXN; i++) {
183+
int t = rand() % 2;
184+
vS.push_back(t + 1);
185+
S.push_back((char)(t + 'a'));
186+
}
187187

188-
// cout << S << endl;
189-
vector<array<int, 2>> res;
190-
{
191-
timeit x("kactl");
192-
old::SuffixArray kactl(S);
193-
// cout << kactl.a[100] << endl;
194-
auto lcp = kactl.lcp();
188+
// cout << S << endl;
189+
vector<array<int, 2>> res;
190+
{
191+
timeit x("kactl");
192+
old::SuffixArray kactl(S);
193+
// cout << kactl.a[100] << endl;
194+
auto lcp = kactl.lcp();
195195
rep(i,0,sz(S)+1)
196-
res.push_back({kactl.a[i], lcp[i]});
197-
}
198-
{
199-
timeit x("MIT");
200-
SuffixArray sa(S);
201-
// cout << sa.sa[100] << endl;
196+
res.push_back({kactl.a[i], lcp[i]});
197+
}
198+
{
199+
timeit x("MIT");
200+
SuffixArray sa(S);
201+
// cout << sa.sa[100] << endl;
202202
rep(i,0,sz(S)+1) {
203-
assert((res[i] == array<int, 2>{sa.sa[i], sa.lcp[i]}));
204-
}
205-
}
206-
}
203+
assert((res[i] == array<int, 2>{sa.sa[i], sa.lcp[i]}));
204+
}
205+
}
206+
}
207207
return 0;
208208
}
209209

210210
void fuzz(bool onlySmall = false) {
211211
rep(large,0,2) {
212212
if (onlySmall && large) break;
213-
double work = large ? 1e8 : 5e5;
213+
double work = large ? 1e7 : 5e5;
214214
rep(alpha,1,27) {
215215
rep(n,0,100) {
216216
if (n * n * pow(alpha, n) > work) break;
217-
cout << alpha << ' ' << n << ": " << flush;
217+
// cout << alpha << ' ' << n << ": " << flush;
218218
string s(n, 'x');
219-
int cnt = 0;
220219
gen(s, 0, alpha, [&]() {
221220
test(s, alpha);
222-
cnt++;
223221
});
224-
cout << cnt << endl;
225222
}
226223
}
227224
}
@@ -255,6 +252,7 @@ void perf2() {
255252
int main() {
256253
// compare();
257254
fuzz(0);
255+
cout<<"Tests passed!"<<endl;
258256
// perf();
259257
// perf2();
260258
}

fuzz-tests/strings/Zfunc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ signed main() {
4848
string s(n, 'x');
4949
gen(s, 0, 4, [&]() { test(s); });
5050
}
51-
cout<<"Passed"<<endl;
52-
}
51+
cout<<"Tests passed!"<<endl;
52+
}

0 commit comments

Comments
 (0)