### gepardo's blog

By gepardo, history, 3 years ago,

Hello, Codeforces!

If you tried to prepare some competitive programming problems, you might parse parameters like this:

#include "testlib.h"
#include <cstdlib>

using namespace std;

int main(int argc, char **argv) {
registerGen(argc, argv, 1);
int n = atoi(argv[1]);
int m = atoi(argv[2]);
int k = atoi(argv[3]);
...


Of course, such way has many disadvantages:

• You need to pass the exact amount of parameters, you cannot define default values for them.
• If you have many parameters, it's easy to forget the order.
• If you pass too few of the them, it will be undefined behavior.

So I developed a library called ParmPars to pass parameters to generators in a more convenient way. You can find it on GitHub. I hope it will help you to generate tests better.

Using ParmPars, you could rewrite the code above in the following way:

#include "testlib.h"
#include "parmpars.hpp"

using namespace std;

int main(int argc, char **argv) {
initGenerator(argc, argv, 1);
DECLARE(int, n);
DECLARE(int, m);
DECLARE(int, k);
...


In ParmPars, all the parameters are named, so to run the generator you can write something like

gen n=1 m=2 k=3


Let's write a simple generator for A+B problem using ParmPars: initGenerator is a function that initializes both Testlib ad ParmPars. DECLARE macros are used to declare a variable and init it from the parameters.

Of course, default parameters can be used:

#include "testlib.h"
#include "parmpars.hpp"

using namespace std;

int main(int argc, char **argv) {
initGenerator(argc, argv, 1);
DECLARE_D(int, n, 1);
DECLARE_D(int, m, 2);
DECLARE_D(int, k, 3);
...


Now if you run gen without parameters, it will assume n=1, m=2 and k=3.

# Using ParmPars in Polygon

Just upload it to Files > Resource Files.

# More powerful example: generator ranges

Let's write a simple generator for A+B problem using ParmPars:

#include "testlib.h"
#include "parmpars.hpp"

using namespace std;

int main(int argc, char **argv) {
initGenerator(argc, argv, 1);
DECLARE_GEN(GenRange<int>, a);
DECLARE_GEN(GenRange<int>, b);
cout << a << " " << b << endl;
return 0;
}


Now we want to generate a test with two random numbers from 1 to 1000. Then, we can just use gen a=[1,1000] b=[1,1000]. It works, because DECLARE_GEN first reads [1,1000], and then converts it to int by calling rnd.next(1, 1000). You can also append the generator seed as a last parameter: gen a=[1,1000] b=[1,1000] randomseed.

# More examples

You can find more examples in the project's README.

# Questions

You can report the issues, ask questions about ParmPars and suggest enhancements in the comments. Obviously, you can also use GitHub's issue and pull request functionality.

• +102