import java.io.*;
import java.util.*;

public class MissionsTestGen {

	final Random rng = new Random(577215664);
	final int MAX_VALUE = 1_000_000_000;

	PrintWriter out;
	boolean isPreliminary;
	int countTests = 0;

	void generate() throws Exception {
		generatePreliminary();
		generateTests();
	}

	void generatePreliminary() {
		isPreliminary = true;
		print(new int[] { 3, 2, 1 }, new int[] { 2, 3, 1 });
	}

	void generateTests() {
		countTests = 0;
		isPreliminary = false;
		generateSmall();
		generateMedium();
		generateBig();
	}

	void generateSmall() {
		print(new int[] { 2 }, new int[] { 9 });
		print(new int[] { 3, 5 }, new int[] { 5, 3 });
		print(new int[] { 4, 6 }, new int[] { 3, 2 });
		print(new int[] { 3, 4, 5 }, new int[] { 4, 5, 3 });
		print(new int[] { 2, 3, 4, 1 }, new int[] { 3, 4, 1, 2 });

		for (int i = 6; i <= 10; i++) {
			printRandom(i, 1, i * 10);
			printOneMax(i, 1, 10 * i);
		}
	}

	private void generateMedium() {
		final int GROUP_SIZE = 25;
		int[] vals = getUniqueArray(GROUP_SIZE, 2000, 10000);
		Arrays.sort(vals);
		for (int i = 0; i < GROUP_SIZE; i++) {
			int minV = 1;
			int maxV = 100_000_000;
			if (rng.nextBoolean()) {
				printRandom(vals[i], minV, maxV);
			} else {
				printOneMax(vals[i], minV, maxV);
			}
		}

	}

	private void generateBig() {
		final int GROUP_SIZE = 10;
		int[] vals = getUniqueArray(GROUP_SIZE, 80000, 100000);
		Arrays.sort(vals);
		for (int i = 0; i < GROUP_SIZE; i++) {
			printRandom(vals[i], MAX_VALUE - 100_000_000, MAX_VALUE);
		}

	}

	void printRandom(int n, int minV, int maxV) {
		int[] a = getUniqueArray(n, minV, maxV);
		int[] b = getUniqueArray(n, minV, maxV);
		print(a, b);
	}

	void printOneMax(int n, int minV, int maxV) {
		int[] a = getUniqueArray(n, minV, maxV);
		int[] b = getUniqueArray(n, minV, maxV);
		moveMax(a);
		moveMax(b);
		shuffleBoth(a, b);
		print(a, b);
	}

	int[] getUniqueArray(int n, int minV, int maxV) {
		while (true) {
			int[] a = new int[n];
			for (int i = 0; i < n; i++) {
				a[i] = randRange(minV, maxV);
			}
			int[] b = a.clone();
			Arrays.sort(b);
			for (int i = 0; i < n - 1; i++) {
				if (b[i] == b[i + 1]) {
					b[i + 1]++;
				}
			}
			Arrays.sort(b);
			boolean ok = true;
			for (int i = 0; i < n - 1; i++) {
				if (b[i] == b[i + 1]) {
					ok = false;
				}
			}
			if (ok) {
				return shuffleArray(b);
			}
		}
	}

	int[] shuffleArray(int[] a) {
		int n = a.length;
		int[] res = a.clone();
		for (int i = 1; i < n; i++) {
			int id = rng.nextInt(i + 1);
			int tmp = res[id];
			res[id] = res[i];
			res[i] = tmp;
		}
		return res;
	}

	void shuffleBoth(int[] a, int[] b) {
		int n = a.length;
		for (int i = 1; i < n; i++) {
			int id = rng.nextInt(i + 1);

			int tmp = a[id];
			a[id] = a[i];
			a[i] = tmp;

			tmp = b[id];
			b[id] = b[i];
			b[i] = tmp;
		}
	}

	void moveMax(int[] a) {
		int max = 0;
		for (int i = 1; i < a.length; i++) {
			if (a[i] > a[max]) {
				max = i;
			}
		}
		int tmp = a[max];
		a[max] = a[0];
		a[0] = tmp;
	}

	class Task {
		int pain, suffering;
		int id;

		public Task(int pain, int suffering, int id) {
			super();
			this.pain = pain;
			this.suffering = suffering;
			this.id = id;
		}
	}

	int randRange(int from, int to) {
		return rng.nextInt(to - from + 1) + from;
	}

	void print(int[] p, int[] s) {
		Task[] t = new Task[p.length];
		for (int i = 0; i < t.length; i++) {
			t[i] = new Task(p[i], s[i], i);
		}
		printTest(t);
	}

	void printTest(Task[] tasks) {
		try {
			countTests++;
			String fileName = (isPreliminary) ? ("../preliminary/")
					: ("../tests/");
			fileName += String.format("%02d", countTests);
			out = new PrintWriter(fileName);

			out.println(tasks.length);
			for (Task t : tasks) {
				out.println(t.pain + " " + t.suffering);
			}
			System.out.println("Done printing test #" + countTests);
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws Exception {
		new MissionsTestGen().generate();
	}
}