// Author: Ivan Kazmenko (gassa@mail.ru)
// Generator for problem "navel-throw"
module gen;
import std.algorithm;
import std.conv;
import std.exception;
import std.format;
import std.random;
import std.range;
import std.stdio;

immutable string testFormat = "%03d";
enum generateAnswers = false;

immutable int minN =       1;
immutable int maxN = 10 ^^ 9;

struct Test
{
	int n;

	string comment;

	void validate () const
	{
		enforce (minN <= n && n <= maxN);
	}

	void print (File f) const
	{
		f.writeln (n);
	}

	string log () const
	{
		return format !("%s (n = %b)") (comment, n);
	}
}

Test [] tests;

void printAllTests ()
{
	foreach (testNumber, test; tests)
	{
		test.validate ();
		auto testString = format (testFormat, testNumber + 1);
		auto f = File (testString, "wt");
		test.print (f);
		static if (generateAnswers)
		{
			auto g = File (testString ~ ".a", "wt");
			test.printAnswer (g);
		}
		writeln (testString, ": ", test.log ());
	}
}

Mt19937 rndLocal;
Unqual !(T) rndValue (T) () {return uniform !(T) (rndLocal);}
Unqual !(T) rndValue (T) (T lim)
    {return uniform (cast (T) (0), lim, rndLocal);}
Unqual !(T) rndValue (string boundaries = "[)", T) (T lo, T hi)
    {return uniform !(boundaries) (lo, hi, rndLocal);}

auto rndChoice (R) (R r) {return r[rndValue (cast (int) (r.length))];}

void rndShuffle (R) (R r)
{
	auto len = r.length.to !(int);
	foreach (i; 0..len)
	{
		int k = rndValue (i, len);
		r.swapAt (i, k);
	}
}

void main ()
{
	rndLocal.seed (357_812_894);
	tests ~= Test (4, "example test 1");
	tests ~= Test (3, "example test 2");
	tests ~= Test (11, "example test 3");

	tests ~= Test (1, "minimal test 1");
	tests ~= Test (2, "minimal test 2");
	tests ~= Test (5, "minimal test 3");
	tests ~= Test (6, "minimal test 4");
	tests ~= Test (7, "minimal test 5");
	tests ~= Test (8, "minimal test 6");
	tests ~= Test (9, "minimal test 7");
	tests ~= Test (10, "minimal test 8");

	tests ~= Test (100, "general test 1");
	tests ~= Test (1111, "general test 2");
	tests ~= Test (0xF00F, "general test 3");
	tests ~= Test (0x8005, "general test 4");
	tests ~= Test ((1 << 29) - 1, "general test 5");
	tests ~= Test (1 << 29, "general test 6");
	tests ~= Test ((1 << 29) + (1 << 13) + 1, "general test 7");
	tests ~= Test (0b10111_00111110_00111111_01111011, "general test 8");
	tests ~= Test (maxN - 1, "general test 9");
	tests ~= Test (maxN, "general test 10");
	tests ~= Test (0x15555555, "general test 11");
	tests ~= Test (0x33333333, "general test 12");
	tests ~= Test (0x3AFFFFFF, "general test 13");
	tests ~= Test (987654321, "general test 14");
	tests ~= Test (123456789, "general test 15");

	printAllTests ();
}
