Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

C++  Module 19 – C++ for DSA and competitive programming

Stress testing contest solutions in C++

Find wrong answers by comparing a fast C++ solution with a brute force on many small random inputs, replay every failure from its seed, and shrink it.

  • Intermediate
  • 30 minutes
  • Examples run with Clang 21.0.0, GCC 16.2.0 and Python 3.14.8
  • By MySmartCoPilot
Free core, Pro depth: 11 of 30 minutes free
Free: A solution can pass both samples and still be wrong · A stress test needs four pieces · The first failing seed names the bug · 2 more sections. With a pass: 2 in-depth parts and 3 interview answers, about 19 minutes.

What you will learn

  • Find wrong answers by comparing a solution with a brute force
  • Choose generator sizes and value ranges that reach boundary bugs
  • Reproduce every failing case from its seed, on any compiler
  • Simplify a failing case to a small input that still fails

Before you start

A solution can pass both samples and still get Wrong answer on test 23, a test the judge never shows you. A A test that runs a solution and a slow but surely correct version of it on many small random inputs and compares their answers, so that the first difference gives a failing input small enough to check by hand. finds such an input for you: it runs your fast solution and a slow, obviously correct one, the The simplest correct solution of a problem, such as checking every pair, written straight from the statement: far too slow for the real limits, but easy to trust as the reference a faster solution is tested against., on thousands of small random inputs and stops at the first input on which their answers differ, small enough to check by hand. It needs four pieces: a generator that makes one input from a seed: The value that sets a random number engine's starting state, such as 42 in std::mt19937 engine(42). The same seed gives the same sequence again; a seed from std::random_device makes each run different. More in “Random numbers in C++: engines, distributions, seeds”, the brute force, the solution under test, and a driver that compares their outputs and prints the seed with every failure, so that the case replays exactly. Use one whenever a solution passes its samples and still fails, or before submitting one whose edge cases you doubt. This lesson builds one for an original problem and catches a boundary bug that both samples miss.

A solution can pass both samples and still be wrong

Close scores. n players have integer scores a₁, …, aₙ. Two players are close when their scores differ by at most d. Count the pairs of players i < j that are close. Constraints: 1 ≤ n ≤ 200,000, 0 ≤ d ≤ 10⁹ and 0 ≤ aᵢ ≤ 10⁹. The input is n and d, then the n scores; the output is one number. Sample 1 is 5 3 with the scores 10 2 6 4 15, sample 2 is 6 4 with 1 20 3 11 30 9, and both answers are 2.

Sorting the scores puts close players next to each other, so two pointers count the pairs in O(n log n): for each score a[j], the scores from a[i] to a[j - 1] are within d of it, and i only ever moves right.

fast.cpp C++ · fast.cpp
// fast.cpp: "Close scores" in O(n log n): sort, then slide two pointers. It passes both samples.
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    int n;
    long long d;
    std::cin >> n >> d;
    std::vector<long long> a(n);
    for (auto& x : a) std::cin >> x;
    std::ranges::sort(a);
    long long pairs = 0;
    int i = 0;  // the first score that is still close enough to a[j]
    for (int j = 0; j < n; ++j) {
        while (i < j && a[j] - a[i] >= d) ++i;
        pairs += j - i;  // a[i], ..., a[j - 1] are each within d of a[j]
    }
    std::cout << pairs << '\n';
}
Both samples Python · samples_session.py
from session import run

# The fast solution on the two samples of the statement: both answers are right.
run("""
clang++ -std=c++23 -O2 -Wall -Wextra fast.cpp -o fast
./fast < sample1.txt
./fast < sample2.txt
""")

Output

$ clang++ -std=c++23 -O2 -Wall -Wextra fast.cpp -o fast
$ ./fast < sample1.txt
2
$ ./fast < sample2.txt
2

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 samples_session.py

Both answers are right, and that is all two samples can show.

Checkpoint

Check: Close scores and its two-pointer solution

  1. Question 1 of 2 Sample 1 has d = 3 and the scores 10 2 6 4 15. Which pairs of scores are close?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: 2 and 4, and 4 and 6

    Sorted, the scores are 2 4 6 10 15. Two players are close when their scores differ by at most d = 3: 4 − 2 = 2 and 6 − 4 = 2 qualify, and every other difference is 4 or more. That gives the sample's answer, 2.

  2. Question 2 of 2 Sample 2 sorted is 1 3 9 11 20 30, with d = 4. When j reaches 11, at position 3, how many pairs does fast.cpp add?

    Type a number.

    A hint

    Find where i stands: the first score that is still close enough to 11. j adds the scores from a[i] to a[j − 1].

    Show the answer: Question 2 of 2

    Answer: 1 pairs

    When j was at 9, the loop moved i past 1 and 3 to position 2. For 11, a[j] − a[i] = 11 − 9 = 2 is within d, so i stays at 2 and j adds j − i = 3 − 2 = 1: the pair 9 and 11. The scores 1 and 3 are 10 and 8 below 11.

A stress test needs four pieces

The four pieces form one loop, repeated once per seed:

The stress-test loop: a seed makes an input, brute force and the fast solution answer it, and a difference stops the loop.seed kgen kone small random inputbrute: every pairslow, easy to trustfast: two pointersthe solution under testsame answer?stop: print seed k,the input and both answersyes: k + 1no

The loop of a stress test

Text description of the diagram

The diagram is a loop of five steps.

  1. "seed k" leads to "gen k", which makes one small random input from the seed.
  2. The input goes to two programs: "brute", which checks every pair and is slow but easy to trust, and "fast", the two-pointer solution under test.
  3. Both answers go to a diamond, "same answer?".
  4. An arrow labelled "yes: k + 1" goes from the diamond back to the seed, so the loop tries the next seed.
  5. An arrow labelled "no" goes to "stop: print seed k, the input and both answers", which is everything needed to replay the failing case.

The brute force checks every pair, O(n²), which is hopeless at n = 200,000 and trivial to get right. The generator makes inputs that are small on purpose: at most 8 scores, from 0 to 9, so that equal scores and exact differences turn up all the time. It uses only the raw numbers of std::mt19937, which the C++ standard fixes, so a seed gives the same input with every standard library:

The brute force and the generator

C++ (brute.cpp) · brute.cpp

// brute.cpp: "Close scores" by checking every pair, O(n²): far too slow for n = 200,000, and easy to trust.
#include <iostream>
#include <vector>

int main() {
    int n;
    long long d;
    std::cin >> n >> d;
    std::vector<long long> a(n);
    for (auto& x : a) std::cin >> x;
    long long pairs = 0;
    for (int i = 0; i < n; ++i)
        for (int j = i + 1; j < n; ++j)
            if (a[i] - a[j] <= d && a[j] - a[i] <= d) ++pairs;
    std::cout << pairs << '\n';
}

C++ (gen.cpp) · gen.cpp

// gen.cpp: one small random input of "Close scores", fully decided by the seed in argv[1].
// It takes the engine's raw numbers and reduces them with %, so every standard library makes the same input from
// the same seed (std::mt19937's numbers are fixed by the C++ standard; distributions are not). The tiny bias of %
// does not matter for test inputs.
#include <cstdlib>
#include <iostream>
#include <random>

int main(int argc, char* argv[]) {
    std::mt19937 engine(static_cast<unsigned>(std::strtoul(argv[1], nullptr, 10)));
    auto pick = [&](unsigned lo, unsigned hi) { return lo + engine() % (hi - lo + 1); };
    unsigned n = pick(1, 8);  // small, so that a failing case is easy to read
    unsigned d = pick(0, 4);
    std::cout << n << ' ' << d << '\n';
    for (unsigned k = 0; k < n; ++k) std::cout << pick(0, 9) << (k + 1 < n ? ' ' : '\n');  // many equal scores
}

The driver is a short shell loop. It writes each input to a file, runs both programs on it, and compares the two outputs with cmp, which POSIX defines to return a non-zero exit status: The number a program hands back when it ends, the value main returns. 0 means success; a shell keeps the last status in $?, and && runs the next command only after a status of 0. More in “How C++ compiles: preprocess, compile and link” when files differ:

stress.sh Shell · stress.sh
#!/bin/sh
# stress.sh: build the three programs, then compare fast with brute on the inputs of seeds 1 to $1, and stop at the
# first difference with everything needed to replay it.
set -e
clang++ -std=c++23 -O2 gen.cpp -o gen
clang++ -std=c++23 -O2 brute.cpp -o brute
clang++ -std=c++23 -O2 "${2:-fast.cpp}" -o fast
seed=1
while [ "$seed" -le "$1" ]; do
    ./gen "$seed" > input.txt
    ./brute < input.txt > expected.txt
    ./fast < input.txt > got.txt
    if ! cmp -s expected.txt got.txt; then
        echo "seed $seed: the outputs differ"
        cat input.txt
        echo "expected $(cat expected.txt), got $(cat got.txt)"
        exit 1
    fi
    seed=$((seed + 1))
done
echo "seeds 1 to $1: no difference"

Follow the driver’s first pass, on seed 1:

Interactive · stage by stage The driver's first pass, on seed 1 Step through one pass of stress.sh. Each stage is one line of its loop; the arrow on the right is the way back to the next seed.
The driver's first pass, on seed 1, step 6 of 6. Showing ./gen 1 > input.txt (d = 4: 4 8 3 3 1 1), ./brute < input.txt (expected.txt: 11), ./fast < input.txt (got.txt: 11), cmp -s, the two files (same: status 0), stop, and print the case (never reached). In focus: cmp -s, the two files.same: next seed./gen 1 > input.txtd = 4: 4 8 3 3 1 1./brute < input.txtexpected.txt: 11./fast < input.txtgot.txt: 11cmp -s, the two filessame: status 0stop, and print the casenever reachedseed 2

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. Seed 1 makes an input. The loop starts at seed 1. gen.cpp seeds std::mt19937 with 1 and draws n = 6, d = 4 and six scores from 0 to 9, which it writes to input.txt.
  2. The brute force answers. brute.cpp checks all 15 pairs of the six scores. 11 of them differ by at most 4, so expected.txt holds 11.
  3. The solution answers. fast.cpp sorts the scores to 1 1 3 3 4 8 and counts with its two pointers. It prints 10, so got.txt holds 10.
  4. cmp finds a difference. cmp -s prints nothing and answers with its exit status: non-zero, because the two files differ. The if in stress.sh therefore runs.
  5. The loop stops. The driver prints seed 1, the input and "expected 11, got 10", then exits with status 1. Running ./gen 1 again makes the same input, so the case can be replayed and checked by hand.
  6. With the fixed solution. Built from fast_fixed.cpp, the solution prints 11 for seed 1 too. cmp answers 0, the loop goes on to seed 2, and seeds 1 to 100 pass without a difference.

Checkpoint

Check: The four pieces of a stress test

  1. Question 1 of 2 The stress test reports "seed 1: the outputs differ". What do you need to replay that case exactly?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The seed and the same generator program

    gen.cpp decides the whole input from the seed, using only the engine's raw numbers, so ./gen 1 prints the same input every time and with every standard library. The driver prints the seed with every failure for exactly this reason.

  2. Question 2 of 2 ./stress.sh 1000 stops with "seed 37: the outputs differ". How many times did it run brute?

    Type a number.

    Show the answer: Question 2 of 2

    Answer: 37 runs

    The loop runs gen, brute and fast once per seed, starting at seed 1, and stops at the first seed whose two outputs differ. Seeds 1 to 37 each ran brute once, 37 runs in all, and seeds 38 to 1,000 never ran.

The first failing seed names the bug

Here is the driver’s run on fast.cpp, then on the fixed version:

The stress test, on fast.cpp and then on the fixed version Python · stress_session.py
from session import run

# The stress test on the fast solution, then on the fixed one. Each case starts gen, brute, fast and cmp, so the
# fixed solution gets 100 cases here; the in-process driver later in the lesson runs far more.
run("""
./stress.sh 1000
./stress.sh 100 fast_fixed.cpp
""")

Output

$ ./stress.sh 1000
seed 1: the outputs differ
6 4
4 8 3 3 1 1
expected 11, got 10
[exit status 1]
$ ./stress.sh 100 fast_fixed.cpp
seeds 1 to 100: no difference

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 stress_session.py

The first seed already failed. Sorted, its scores are 1 1 3 3 4 8, and with d = 4 the brute force counted 11 close pairs: the 10 pairs among 1, 1, 3, 3 and 4, plus 4 and 8, whose difference is exactly 4. The fast solution counted 10, because its loop moved i on while a[j] - a[i] >= d, which treats a difference of exactly d as too far. Step through the loop on these six scores and watch the pair 4 and 8 go missing:

Interactive · step by step Where fast.cpp loses a pair, on the input of seed 1 Step through the loop for each position j. The left column holds the sorted scores; the right one says where i stands and how many pairs j adds.
Where fast.cpp loses a pair, on the input of seed 1, step 7 of 7. Showing a[0] = 1 (more than 4 below 8), a[1] = 1 (more than 4 below 8), a[2] = 3 (more than 4 below 8), a[3] = 3 (more than 4 below 8), a[4] = 4 (kept: 8 − 4 = 4, within d), a[5] = 8, j = 0 (i = 0: adds 0, total 0), j = 1 (i = 0: adds 1, total 1), j = 2 (i = 0: adds 2, total 3), j = 3 (i = 0: adds 3, total 6), j = 4 (i = 0: adds 4, total 10), j = 5 (i = 4: adds 1, total 11). In focus: a[4] = 4, j = 5.a[0] = 1more than 4 below 8a[1] = 1more than 4 below 8a[2] = 3more than 4 below 8a[3] = 3more than 4 below 8a[4] = 4kept: 8 − 4 = 4, within da[5] = 8j = 0i = 0: adds 0, total 0j = 1i = 0: adds 1, total 1j = 2i = 0: adds 2, total 3j = 3i = 0: adds 3, total 6j = 4i = 0: adds 4, total 10j = 5i = 4: adds 1, total 11

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. The failing input, sorted. fast.cpp sorts the six scores of seed 1 to 1 1 3 3 4 8; d is 4. For each position j it moves i to the first score close enough to a[j], then adds j − i, the scores from a[i] to a[j − 1].
  2. j = 0. a[0] = 1 has no score before it, so i stays at 0 and j adds 0.
  3. j = 1. 1 − 1 = 0 is within 4, so i stays at 0 and j adds 1: the pair of the two 1s.
  4. j = 2, 3 and 4. 3, 3 and 4 are each within 4 of a[0] = 1, so i does not move and they add 2, 3 and 4: the 10 pairs among 1, 1, 3, 3 and 4.
  5. j = 5: 8 is far away. For a[5] = 8, the scores 1, 1, 3 and 3 differ from it by 7 and 5, more than d, so the while loop moves i past all four of them, to position 4.
  6. The bug: 8 − 4 = 4. Now a[i] = 4, and 8 − 4 = 4 is exactly d. fast.cpp moves i on while a[j] − a[i] >= d, and 4 >= 4 holds, so i moves to 5 and j adds 0. The pair 4 and 8 is lost, and the total stays at 10.
  7. The fix: > instead of >=. fast_fixed.cpp moves i only while a[j] − a[i] > d. 4 > 4 is false, so i stops at 4 and j adds 5 − 4 = 1: the total is 11, the brute force's answer.

The fix is >, after which the pointer can never pass j, so the i < j guard goes too:

fast_fixed.cpp C++ · fast_fixed.cpp
// fast_fixed.cpp: fast.cpp with its boundary fixed. A pair whose scores differ by exactly d is close, so the left
// pointer moves only while the difference is greater than d.
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    int n;
    long long d;
    std::cin >> n >> d;
    std::vector<long long> a(n);
    for (auto& x : a) std::cin >> x;
    std::ranges::sort(a);
    long long pairs = 0;
    int i = 0;
    for (int j = 0; j < n; ++j) {
        while (a[j] - a[i] > d) ++i;  // stops at i == j at the latest: a[j] - a[j] is 0
        pairs += j - i;
    }
    std::cout << pairs << '\n';
}

The fixed solution matched the brute force on all 100 seeds. Both samples had passed because neither contains two scores exactly d apart, which is typical: samples show the format, not every edge.

Checkpoint

Check: Reading the first failing case

  1. Question 1 of 2 For seed 1, d = 4 and the scores 4 8 3 3 1 1, brute counted 11 pairs and fast counted 10. Which pair did fast miss?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: 4 and 8

    8 − 4 is exactly d, so the pair is close. fast moved its left pointer past 4 because its loop condition was a[j] − a[i] >= d, which treats a difference of exactly d as too far. 8 − 3 is 5, which really is too far.

  2. Question 2 of 2 fast.cpp, with its >= test, runs on d = 2 and the scores 0 2 2 5. The brute force prints 3. What does fast.cpp print?

    Type a number.

    A hint

    Step through j = 1, 2 and 3 as the figure does: the loop moves i on while a[j] − a[i] >= 2.

    Show the answer: Question 2 of 2

    Answer: 1 pairs

    At j = 1, 2 − 0 = 2 >= 2 moves i to 1, so j adds 0 and the pair 0 and 2 is lost. At j = 2, 2 − 2 = 0 stops i at 1 and j adds 1, the two 2s. At j = 3, 5 − 2 = 3 moves i to 3 and j adds 0. fast prints 1 where the brute force finds 3: both pairs exactly 2 apart are lost.

Small inputs with narrow ranges reach the bugs

A stress test finds a bug only when its inputs can reach it, so the generator matters more than the loop. These are the first six inputs that gen.cpp makes:

The inputs of seeds 1 to 6 Python · inputs_session.py
from session import run

# The first six inputs gen.cpp makes, each on one line: n and d, then the scores.
run("""
clang++ -std=c++23 -O2 gen.cpp -o gen
for s in 1 2 3 4 5 6; do echo "seed $s: $(echo $(./gen $s))"; done
""")

Output

$ clang++ -std=c++23 -O2 gen.cpp -o gen
$ for s in 1 2 3 4 5 6; do echo "seed $s: $(echo $(./gen $s))"; done
seed 1: 6 4 4 8 3 3 1 1
seed 2: 1 2 1
seed 3: 3 3 7 7 0
seed 4: 3 4 1 3 9
seed 5: 4 4 7 5 6 0
seed 6: 3 1 3 2 4

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 inputs_session.py

Repeated scores and scores exactly d apart turn up within a few seeds. Four habits make a stress test find such cases:

  • Small sizes keep a failing case readable and let the brute force run thousands of times a second.
  • Small value ranges make duplicates, equal scores and exact differences common, which is where boundaries break.
  • An independent brute force shares no code or shortcut with the solution, so the two cannot be wrong together.
  • A seed per case, printed with every failure, turns a random input into a test you can run again.

Key idea

Keep inputs small and ranges narrow, so that boundaries appear often, and print the seed of every failure.

The rest of a good stress-testing setup builds on these:

  • An in-process driver calls both solutions as functions, without starting programs for every case.
  • Making a failing test input smaller by removing or lowering one part at a time, and keeping each change only while the input still fails, so that a small case remains that shows the bug. removes and lowers parts of a failing input while it still fails. The smaller the case, the sooner it shows the bug.
  • Running a solution on every possible input up to a small size, in order of size, so that the first failure found is also a smallest one. tries every input up to a small size, so the first failure is also a smallest one.
  • A A program that judges an answer by checking it against the problem's rules, instead of comparing it with one expected output, for problems that accept more than one right answer. validates an answer instead of comparing it with one expected output, for problems with many right answers.
  • Structured generators make trees, graphs and permutations that are valid by construction.
  • A hand-made maximum test reaches what small inputs cannot, such as overflow and slowness.

Checkpoint

Check: Inputs that reach the bugs

  1. Question 1 of 2 The problem allows scores up to 10^9, yet gen.cpp draws them from 0 to 9. Why?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Small ranges make equal scores and exact differences common, and boundary bugs hide in those cases

    A bug at the boundary, such as a pair whose scores differ by exactly d, needs an input with that exact difference. With scores from 0 to 9 and d from 0 to 4 such inputs are common; with scores up to 10^9 two random scores almost never differ by exactly d.

  2. Question 2 of 2 Seed 6 makes d = 1 and the scores 3 2 4. What do brute.cpp and fast.cpp print for it?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: brute 2, fast 0

    Sorted, the scores are 2 3 4. 3 − 2 = 1 and 4 − 3 = 1 are exactly d, so brute counts 2; 4 − 2 = 2 is too far. fast moves i on while a[j] − a[i] >= 1, so it counts neither pair and prints 0. A narrow range makes such inputs common: this is only the sixth seed.

Practise

Practice that adapts to you

Practise this lesson

12 questions about 11 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 12 Why does fast.cpp sort the scores before it counts?

    Choose one answer.

    Show the answer: Question 1 of 12

    Answer: In sorted order the scores close to a[j] sit just before it, so i only ever moves right

    In a sorted array, the scores within d of a[j] among a[0..j − 1] form one block that ends just before j, and its left end never moves back as j grows. So two pointers count every pair in one pass after an O(n log n) sort.

  2. Question 2 of 12 Sample 1 sorted is 2 4 6 10 15, with d = 3. How many pairs does fast.cpp add when j reaches 6, at position 2?

    Type a number.

    Show the answer: Question 2 of 12

    Answer: 1 pairs

    i stands at 0 when j reaches 6. 6 − 2 = 4 is at least 3, so the loop moves i to 1; 6 − 4 = 2 is not, so it stops there, and j adds 2 − 1 = 1, the pair 4 and 6. The >= slip does no harm here: no difference equals d.

  3. Question 3 of 12 brute.cpp needs O(n²) time, hopeless at n = 200,000. Why write it at all?

    Choose one answer.

    Show the answer: Question 3 of 12

    Answer: It follows the statement so directly that it is easy to trust, and on tiny inputs its speed does not matter

    A stress test needs an answer it can trust for every random input. brute.cpp checks every pair exactly as the statement defines a close pair, so it is hard to get wrong, and on inputs of at most 8 scores its O(n²) cost does not matter.

  4. Question 4 of 12 What does cmp -s expected.txt got.txt tell stress.sh?

    Choose one answer.

    Show the answer: Question 4 of 12

    Answer: Whether the two files are the same, through its exit status: 0 when they match

    cmp -s compares the two files byte by byte and prints nothing; its exit status is 0 when they are identical and 1 when they differ. The line if ! cmp -s … in stress.sh runs its failure branch exactly when the status is not 0.

  5. Question 5 of 12 Which change to the stress test would make the seed it prints useless for replaying a failure?

    Choose one answer.

    Show the answer: Question 5 of 12

    Answer: Seeding the generator's engine from the clock instead of from the loop's seed

    A failure replays because the seed alone decides the input. With an engine seeded from the clock, every run makes different inputs, and the printed seed no longer names the failing case.

  6. Question 6 of 12 You stress test a new problem: the shortest path in a small weighted graph. Which pieces must you write anew?

    Choose every answer that is right.

    Show the answer: Question 6 of 12

    Answer:

    • A generator of small graphs
    • A brute force for shortest paths

    The driver and cmp know nothing about the problem: they run two programs on one input and compare what they print. The generator and the brute force belong to the problem, so those are what a new problem needs.

  7. Question 7 of 12 Why did fast.cpp pass both samples, although it has the >= bug?

    Choose one answer.

    Show the answer: Question 7 of 12

    Answer: Neither sample has two scores exactly d apart

    The two tests differ only when a[j] − a[i] equals d. In sample 1 (d = 3) and sample 2 (d = 4) no two scores differ by exactly d, so both versions print 2. Samples show the format, not every edge.

  8. Question 8 of 12 fast.cpp, with its >= test, runs on d = 0 and the scores 7 7 7. What does it print?

    Type a number.

    Show the answer: Question 8 of 12

    Answer: 0 pairs

    With d = 0 only equal scores are close, so the right answer is 3. But 7 − 7 = 0 >= 0 holds, so at j = 1 and at j = 2 the loop moves i up to j and adds nothing: fast prints 0.

  9. Question 9 of 12 fast_fixed.cpp dropped the i < j guard from its while loop. Why can i still never pass j?

    Choose one answer.

    Show the answer: Question 9 of 12

    Answer: When i reaches j, a[j] − a[i] is 0, which is never more than d

    With i = j the difference a[j] − a[i] is 0, and 0 > d is false for every d ≥ 0, so the loop stops. The old guard was needed only because 0 >= d holds when d is 0.

  10. Question 10 of 12 Why does the driver print the seed with every failure?

    Choose one answer.

    Show the answer: Question 10 of 12

    Answer: The seed makes the whole input again, so the failing case can be rerun and kept as a test

    gen.cpp builds each input from its seed alone, so the seed is a complete name for the case: printed with the failure, it turns a random input into a test you can run again.

  11. Question 11 of 12 A problem's values go up to 10^18, and you suspect a bug that needs two equal values. Which generator finds it fastest?

    Choose one answer.

    Show the answer: Question 11 of 12

    Answer: Up to 8 values from 0 to 5

    A bug that needs equal values needs inputs in which values repeat. A narrow range makes repeats common, as gen.cpp's 0 to 9 does; a range as wide as the constraints makes them almost impossible.

  12. Question 12 of 12 A teammate writes the brute force as a loop over every pair, but with fast.cpp's boundary: a pair counts only when its two scores differ by less than d. What does the stress test report?

    Choose one answer.

    Show the answer: Question 12 of 12

    Answer: No difference on any seed, although both programs are wrong

    An independent brute force shares no code or shortcut with the solution. This one shares the boundary test, so it treats exactly d as too far, as fast.cpp does: the two agree on every input and the bug stays hidden.

Faster loops, failures that replay anywhere, and automatic shrinking Pro: opens with a Pro, Premium or Ultimate pass

A shell loop is fine for a first look, but it spends most of its time starting programs. This part moves the stress test into one process, measures how often the bug shows up for different value ranges, makes failures replay on any compiler, and shrinks a failing input automatically.

In this part:

  • A million cases in one process, with the bug rate per value range measured
  • Failures that replay on another compiler
  • Shrinking a failing case automatically

1 diagram · 7 runnable examples (C header, C++, Python) · about 9 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Beyond comparing outputs: exhaustive search, checkers and the bugs small tests miss Pro: opens with a Pro, Premium or Ultimate pass

Random comparison is one tool among several. This part enumerates every small input, judges answers with a checker when many outputs are right, shows the two kinds of bug that small random inputs cannot reach, and ends with an exercise on three more broken solutions.

In this part:

  • Generators for inputs with structure
  • Every input up to four scores, checked exhaustively
  • A checker when many answers are right
  • What small random tests cannot find, with numbers
  • Your turn: three solutions that pass both samples

10 runnable examples (C++, C++ (int_count.cpp), C++ (max_test.cpp), C++ (solution_a.cpp), C++ (solution_b.cpp), C++ (solution_c.cpp), Python) · about 10 minutes

Opening this part with your pass…Pro part. It opens with the same pass as the part above.

Interview questions

  1. Fresher · Warm-up

    What is a stress test in competitive programming, and which four pieces does it need?

    A stress test runs your fast solution and a slow but obviously correct one, the brute force, on many small random inputs, compares their outputs and stops at the first input on which they differ. It needs four pieces: a generator that makes one input from a seed, the brute force, the solution under test, and a driver that runs both on each input and compares the answers, for example a shell loop with cmp. The driver prints the seed and the input with every failure, so the case can be replayed and checked by hand. Small sizes and narrow value ranges matter: they make duplicates and exact boundaries common, which is where most wrong answers hide.

  2. Fresher to mid

    Your solution passes the samples but gets Wrong Answer on test 23, which the judge does not show. Design a stress test to find a failing case: what do you generate, how do you make sure the brute force is right, and what do you do with the first difference?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Mid to senior

    Your stress test ran a million random cases without a single difference, but the judge still reports Wrong Answer. Name the likely reasons, and say how you would check each one.

    Model answer, Pro. First step and follow-ups

  4. Mid to senior

    Your stress test reports a failure at seed 4711. A teammate builds the same files with another compiler and gets a different input for that seed, which passes. Why, and how do you design the generator and the report so that every failure replays everywhere?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • fast.cpp passed both samples while it lost every pair of scores exactly d apart.
  • A stress test needs a seeded generator, a trusted brute force, the solution and a driver that stops at the first difference.
  • The first failing case, read against the brute force’s count, named the bug: >= where “at most d” needs >.
  • Small inputs with narrow value ranges make boundaries common, and a seed per case makes every failure replay.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.