cf/mirror

Stress testing

Stress testing means: write a slow-but-obviously-correct brute, write a generator that produces tiny random tests, then hammer your fast solution against the brute until they disagree. cf-mirror runs all three on every iteration and shows you the first failing input.

When should I use it?

  • WA on sample 4+ with no idea why → stress against an O(n!) brute on n ≤ 6.
  • WA on systests, AC on samples → brute can probably find the edge case.
  • You added an optimization and want to verify it didn't break anything.
  • Tricky greedy / DP where you suspect a counterexample exists.

The three programs

All three programs use the language picked in the editor. cf-mirror compiles each independently — they don't share globals or includes.

  1. Generator. Reads seed from stdin (a positive integer). Prints one random test input. Use the seed to drive your RNG so the same iteration always produces the same test — that's how the Replay button works.
  2. Solution. Your main editor code. Read the input, print the answer. This is the fast solution you're actually trying to validate.
  3. Brute. A slow-but-obviously-correct reference. O(n!), full backtracking, exhaustive search — whatever's easiest to get right. It only needs to be correct on tiny inputs.

Worked example — finding a counter to a buggy 'max subarray sum' solution

Suppose your solution looks like this (buggy: forgets the empty-subarray case):

// Solution
#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    vector<int> a(n);
    for (auto& x : a) cin >> x;
    int best = a[0], cur = a[0];
    for (int i = 1; i < n; ++i) {
        cur = max(a[i], cur + a[i]);
        best = max(best, cur);
    }
    cout << best << "\n";
}

Generator — keep n tiny (≤ 5) and values in [-5, 5] so corner cases are common:

// Generator
#include <bits/stdc++.h>
using namespace std;
int main() {
    int seed; cin >> seed;
    mt19937 rng(seed);
    int n = rng() % 5 + 1;        // 1..5
    cout << n << "\n";
    for (int i = 0; i < n; ++i)
        cout << ((int)(rng() % 11) - 5) << " ";   // [-5, 5]
    cout << "\n";
}

Brute — exhaustive over all subarrays:

// Brute
#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    vector<int> a(n);
    for (auto& x : a) cin >> x;
    int best = INT_MIN;
    for (int l = 0; l < n; ++l) {
        int s = 0;
        for (int r = l; r < n; ++r) {
            s += a[r];
            best = max(best, s);
        }
    }
    cout << best << "\n";
}

Click ▶ Run stress test. Within a couple seconds you'll likely see a counterexample like n=2, a=[-3, -1] where your solution prints something subtle vs the brute's -1 (both correct here actually, because we read the spec carefully). The point: when there IS a bug, this loop finds it in seconds.

Saved finds + Replay

Every confirmed mismatch is auto-saved per problem (per language) into the Saved finds list at the bottom of the stress panel. Each row has three buttons:

  • ▶ Replay — re-runs the SAME seed against your CURRENT editor code, with iterations=1. Perfect for "did my fix work?"
  • ⧉ Copy input — drops the failing test into your clipboard. Paste it into the Custom test box on the problem page to debug interactively.
  • — forget this single find. Finds are scoped per (problem, language).

Finds persist across reloads (localStorage). The list is capped at 30 most-recent per (problem, language) so it doesn't grow forever.

Tips that actually matter

  • Keep n small. If the brute is O(n!) or O(2^n), n ≤ 6 still finishes in milliseconds and almost every edge case appears. Larger n just slows the loop without finding more bugs.
  • Seed the RNG. Always use mt19937 rng(seed), neversrand(time(0)) — the latter makes Replay useless.
  • Include the corner. If your input range is [1, 10^9], generate [1, 5] in the stress generator. You're trying to expose bugs, not stress the judge.
  • Print outputs exactly. Trailing whitespace and missing newlines count as "different" in the comparator. cf-mirror visually marks these in the diff view.
  • Crank iterations only if the bug is rare. 50 is the default and catches most bugs in < 30 seconds; bump to 200 if you suspect a 1-in-thousands edge case.

Related

  • Templates docs — how to set up the file scaffolds the stress generator lives in.
  • On any problem page, expand the Stress test section to use this in practice.