#define PROBLEM_VERSION_DIV1 1
#define PROBLEM_VERSION_DIV2 2
#define PROBLEM_VERSION PROBLEM_VERSION_DIV1
#define PROBLEM_NAME "revolving-lasers"
#define TEST_STR "%03d"
#include "gentools.h"
#include <cassert>
#include <set>
#include <vector>

#ifdef WIN32
#define INT64 "%I64d"
#else
#define INT64 "%lld"
#endif

#ifdef DEBUG
#define eprintf(...) fprintf (stderr, __VA_ARGS__)
#else
#define eprintf(...) assert (true)
#endif

using namespace std;

int const MIN_N =  0;
int const MED_N =  2;
int const MAX_N =  3;
int const MIN_C =  2;
int const MAX_C = 10;
int const MED_A =  1;
int const MAX_A =  3;
#if PROBLEM_VERSION == PROBLEM_VERSION_DIV1
int const LIM_N = MAX_N;
int const LIM_A = MAX_A;
#else
int const LIM_N = MED_N;
int const LIM_A = MED_A;
#endif

struct laser
{
	int x, y, a;
};

struct coord
{
	int x, y;
	coord (int nx, int ny): x (nx), y (ny) {}
	bool operator < (coord const & other) const
	{
		if (x != other.x)
		{
			return x < other.x;
		}
		return y < other.y;
	}
};

laser p [MAX_N];
int n;


void do_nothing (void)
{
// do nothing
}

void open_test (void)
{
	n = 0;
}

void close_test (void)
{
	do_nothing ();
}

void log_test (void)
{
	fprintf (flog, "n = %d", n);
}

void shuffle_test (void)
{
	do_nothing ();
}

void verify_test (void)
{
	assert (MIN_N <= n && n <= LIM_N);

	set <coord> s;
	for (int i = 0; i < n; i++)
	{
		assert ((MIN_C <= p[i].x) && (p[i].x <= MAX_C));
		assert (p[i].x % 2 == 0);
		assert ((MIN_C <= p[i].y) && (p[i].y <= MAX_C));
		assert (p[i].y % 2 == 0);
		assert ((-LIM_A <= p[i].a) && (p[i].a <= +LIM_A));
		coord t = coord (p[i].x, p[i].y);
		assert (s.find (t) == s.end ());
		s.insert (t);
	} 
}

void output_test (void)
{
	FILE * fout;

	fout = fopen (cur_test_str, "wt");
	assert (fout != NULL);

	fprintf (fout, "%d\n", n);
	for (int i = 0; i < n; i++)
	{
		fprintf (fout, "%d %d %d\n", p[i].x, p[i].y, p[i].a);
	}
	
	fclose (fout);
}


void add_laser (int x, int y, int a)
{
	assert (n < LIM_N);
	p[n].x = x;
	p[n].y = y;
	p[n].a = a;
	n++;
}


void gen_samples (void)
{
	shuffle_flag = false;
	
	START_TEST ("first example");
	add_laser ( 2,  2, +1);
	END_TEST ();

	START_TEST ("second example");
	add_laser ( 2,  2, +1);
	add_laser ( 4,  2, -1);
	END_TEST ();
}

void gen_corner_one (void)
{
	shuffle_flag = false;
	
	int t = 0;
	for (int x = MIN_C; x <= MAX_C; x += MAX_C - MIN_C)
	{
		for (int y = MIN_C; y <= MAX_C; y += MAX_C - MIN_C)
		{
			for (int a = -LIM_A; a <= +LIM_A; a++)
			{
				if (x == 2 && y == 2 && a == +1)
				{
					continue; // first example
				}

				START_TEST ("corner test one %d", t + 1);
				add_laser (x, y, a);
				END_TEST ();
				t++;
			}
		}
	}
}

void gen_small (void)
{
	shuffle_flag = false;
	
	START_TEST ("minimal test");
	END_TEST ();
	
	START_TEST ("second example variation 1");
	add_laser ( 2,  2, +1);
	add_laser ( 4,  4, -1);
	END_TEST ();

	START_TEST ("second example variation 2");
	add_laser ( 4,  2, +1);
	add_laser ( 2,  2, -1);
	END_TEST ();

	START_TEST ("second example variation 3");
	add_laser ( 2,  2, +1);
	add_laser ( 2,  4, -1);
	END_TEST ();

	START_TEST ("second example variation 4");
	add_laser ( 2,  4, +1);
	add_laser ( 2,  2, -1);
	END_TEST ();
	
	START_TEST ("small hand test 1");
	add_laser ( 2,  2, +1);
	add_laser (10, 10, -1);
	END_TEST ();

	START_TEST ("small hand test 2");
	add_laser ( 2,  2,  0);
	add_laser (10, 10, -1);
	END_TEST ();

	START_TEST ("small hand test 3");
	add_laser ( 8,  2,  0);
	add_laser (10, 10, -1);
	END_TEST ();
	
	START_TEST ("small hand test 4");
	add_laser ( 8,  2,  0);
	add_laser (10, 10, +1);
	END_TEST ();
	
	START_TEST ("small hand test 5");
	add_laser (10,  2, +1);
	add_laser ( 2, 10, -1);
	END_TEST ();

	START_TEST ("small hand test 6");
	add_laser (10,  2, -1);
	add_laser ( 2, 10, +1);
	END_TEST ();

	START_TEST ("small hand test 7");
	add_laser (10,  2, +1);
	add_laser ( 2, 10, +1);
	END_TEST ();
	
	START_TEST ("small hand test 8");
	add_laser (10,  8, -1);
	add_laser ( 2,  4, -1);
	END_TEST ();
	
	START_TEST ("small hand test 9");
	add_laser ( 6,  6, -1);
	add_laser ( 6,  4, -1);
	END_TEST ();
	
	START_TEST ("small hand test 10");
	add_laser (10,  2, +1);
	add_laser ( 8,  2, +1);
	END_TEST ();
	
	START_TEST ("small hand test 11");
	add_laser ( 4,  6,  0);
	add_laser ( 6,  4,  0);
	END_TEST ();
	
	START_TEST ("small hand test 12");
	add_laser ( 2,  2,  0);
	add_laser ( 2, 10,  0);
	END_TEST ();
	
	START_TEST ("small hand test 13");
	add_laser ( 2,  2,  0);
	add_laser ( 2, 10, -1);
	END_TEST ();
	
	START_TEST ("small hand test 14");
	add_laser ( 2, 10,  0);
	add_laser ( 2,  2, +1);
	END_TEST ();
	
	START_TEST ("small hand test 15");
	add_laser ( 4,  2, +1);
	add_laser ( 2, 10,  0);
	END_TEST ();
}

void gen_large (void)
{
	shuffle_flag = false;
	
	START_TEST ("large hand test 1");
	add_laser ( 2,  2, -1);
	add_laser ( 2,  4, -1);
	add_laser ( 4,  4, +2);
	END_TEST ();

	START_TEST ("large hand test 2");
	add_laser ( 2,  2, -1);
	add_laser ( 4,  6, -1);
	add_laser (10,  8, +2);
	END_TEST ();
	
	START_TEST ("large hand test 3");
	add_laser ( 2, 10, -3);
	add_laser ( 4,  6, +2);
	add_laser (10,  2, -1);
	END_TEST ();

	START_TEST ("large hand test 4");
	add_laser ( 2, 10, +1);
	add_laser ( 2,  6, -2);
	add_laser (10,  2, +3);
	END_TEST ();

	START_TEST ("large hand test 5");
	add_laser ( 2, 10, +1);
	add_laser ( 4,  6, -2);
	add_laser (10,  2, +3);
	END_TEST ();

	START_TEST ("large hand test 6");
	add_laser ( 2, 10, +1);
	add_laser ( 4,  8, -3);
	add_laser (10,  2, +2);
	END_TEST ();

	START_TEST ("large hand test 7");
	add_laser ( 2, 10, +1);
	add_laser ( 4,  8, +2);
	add_laser (10,  2, -3);
	END_TEST ();

	START_TEST ("large hand test 8");
	add_laser ( 2, 10, +3);
	add_laser ( 4,  8, +3);
	add_laser (10,  2, -3);
	END_TEST ();

	START_TEST ("large hand test 9");
	add_laser ( 2, 10,  3);
	add_laser ( 4,  8,  3);
	add_laser (10,  2, -2);
	END_TEST ();

	START_TEST ("large hand test 10");
	add_laser ( 2, 10,  3);
	add_laser ( 4,  8,  2);
	add_laser (10,  2, -1);
	END_TEST ();

	START_TEST ("large hand test 11");
	add_laser ( 2,  2, +3);
	add_laser (10, 10, -3);
	END_TEST ();

	START_TEST ("large hand test 12");
	add_laser ( 2,  2,  0);
	add_laser (10, 10, -3);
	END_TEST ();

	START_TEST ("large hand test 13");
	add_laser ( 8,  2,  0);
	add_laser (10, 10, -3);
	END_TEST ();
	
	START_TEST ("large hand test 14");
	add_laser ( 8,  2,  0);
	add_laser (10, 10, +3);
	END_TEST ();
	
	START_TEST ("large hand test 15");
	add_laser (10,  2, +3);
	add_laser ( 2, 10, -3);
	END_TEST ();

	START_TEST ("large hand test 16");
	add_laser (10,  2, -3);
	add_laser ( 2, 10, +3);
	END_TEST ();
	
	START_TEST ("large hand test 17");
	add_laser (10,  2, +3);
	add_laser ( 2, 10, -2);
	END_TEST ();

	START_TEST ("large hand test 18");
	add_laser (10,  2, -3);
	add_laser ( 2, 10, +2);
	END_TEST ();
	
	START_TEST ("large hand test 19");
	add_laser (10,  2, +1);
	add_laser ( 2, 10, -3);
	END_TEST ();

	START_TEST ("large hand test 20");
	add_laser (10,  2, -1);
	add_laser ( 2, 10, +3);
	END_TEST ();
	
	START_TEST ("large hand test 21");
	add_laser ( 2,  2, +2);
	add_laser ( 6,  6, +3);
	add_laser (10, 10, +1);
	END_TEST ();
	
	START_TEST ("large hand test 22");
	add_laser ( 2,  2, -3);
	add_laser ( 6,  6, -1);
	add_laser (10, 10, -2);
	END_TEST ();

	START_TEST ("large hand test 23");
	add_laser ( 2,  2, -1);
	add_laser ( 2,  6, -1);
	add_laser (10,  8, +2);
	END_TEST ();

	START_TEST ("large hand test 24");
	add_laser ( 2,  2, -3);
	add_laser (10, 10, +2);
	END_TEST ();

	START_TEST ("large hand test 25");
	add_laser ( 4,  4, -3);
	add_laser (10, 10, +2);
	END_TEST ();

	START_TEST ("large hand test 26");
	add_laser ( 6,  6, -3);
	add_laser (10, 10, +2);
	END_TEST ();

	START_TEST ("large hand test 27");
	add_laser ( 8,  8, -3);
	add_laser (10, 10, +2);
	END_TEST ();

	START_TEST ("large hand test 28");
	add_laser ( 4,  2, -3);
	add_laser (10, 10, +2);
	END_TEST ();

	START_TEST ("large hand test 29");
	add_laser ( 2,  8, +2);
	add_laser (10, 10, -3);
	END_TEST ();

	START_TEST ("large hand test 30");
	add_laser ( 2,  8, +2);
	add_laser (10, 10, -3);
	add_laser ( 4,  8, +3);
	END_TEST ();

	START_TEST ("large hand test 31");
	add_laser ( 2,  8,  0);
	add_laser (10, 10, -3);
	add_laser ( 4,  8,  0);
	END_TEST ();

	START_TEST ("large hand test 32");
	add_laser ( 2,  6,  0);
	add_laser ( 2, 10,  0);
	add_laser ( 6,  8,  0);
	END_TEST ();

	START_TEST ("large hand test 33");
	add_laser ( 6,  4,  0);
	add_laser ( 6,  6, +1);
	add_laser ( 6,  8,  0);
	END_TEST ();
}


int main (int argc, char * argv [])
{
	init_gen (argc, argv);

	gen_samples ();

	gen_corner_one ();

	gen_small ();

#if PROBLEM_VERSION == PROBLEM_VERSION_DIV1
	gen_large ();
#endif

	exit_gen ();
	
	return 0;
}
