Generate tests

Instead of uploading every input and answer file by hand, you can have a program produce them. A generator is a script stored with the problem; a test names a generator and passes it arguments, and the system runs it to produce that test's data.

Generators print their data to standard output. An answer generator additionally receives the test's input on standard input, which is why the author's own solution usually works as an answer generator with no changes at all — upload the inputs, and let the solution compute the answers.

Generators live on the problem's Testing tab, under Generators. You need permission to write problems.

Add a generator

  1. Open Problems, select the problem, and go to the Testing tab.

  2. Click the Generators row. It reports how many the problem has and opens the list — or the blank editor, if there are none yet.

  3. Click Add generator.

  4. Give it a name, choose a runtime, paste the source, and add additional files if the program needs any.

  5. Save.

The name matters more than it looks: tests refer to a generator by name, not by an internal id. Renaming a generator breaks every test that calls it.

Use a generator in a test

  1. Open the test, or add one.

  2. On Input or Answer, switch the control from test data to a generator.

  3. Pick the generator by name and type its arguments.

  4. Save.

The editor shows Generation Pending between switching and saving, with a Reset to go back to the previous generator. After saving, the system schedules a generation task; you can watch it on the problem's Activity tab, along with the space's other background tasks.

Input and answer are chosen independently, so uploaded input with a generated answer is a perfectly ordinary test.

Generate the answers with the author's solution

This is the most common use, and the least work:

  1. Add a generator named solution, choose the runtime, and paste the author's solution unchanged.

  2. Upload the input data for each test as usual.

  3. On each test, set Answer to the solution generator with no arguments.

The solution receives the test's input on standard input and prints the answer, which becomes the stored answer for that test.

Generate the input too

An input generator takes its parameters from the arguments you give it in the test, so one script covers a whole family of tests. A generator producing a single random integer between two bounds:

import random
import sys

if len(sys.argv) != 3:
    print("Usage: gen <lower_bound> <higher_bound>")
    sys.exit(1)

lower = int(sys.argv[1])
higher = int(sys.argv[2])

print(random.randint(lower, higher))

Saved as a generator named gen, it is called from a test as gen 10 20. Add more tests with different bounds and you have covered the range without writing a file.

Pair it with the solution generator above and neither the input nor the answer of those tests is stored by hand.

When generation happens

Generation runs in the background. A test stays Pending until its data has been generated and validated, and only then does it show Ready. If a submission arrives for a problem whose tests are still pending, the data is generated inline as part of judging that submission — correct, but slower, and worth avoiding during a live contest.

A test that could not be generated shows Invalid, with the reason on hover and the full error at the top of its editor.

Make generators deterministic

A generator must produce the same data every time it is run with the same arguments. Test data is regenerated whenever the generator or the test's arguments change, and a generator that returns something different each time silently changes what the problem asks — including for participants who have already submitted.

Seeding the random number generator from a hash of the arguments is the usual way to get this. Libraries written for the purpose, testlib.h among them, handle it for you; using one is not required, but it is what most problem authors do.

If you want the data checked as well as generated, add a validator — it reads each test's input and asserts that the problem's constraints actually hold.