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

public class TestsGen {
	static int testcount = 0;

	static Random random = new Random(747343);
	
	static int MAXN = 100000;
	static int MAXC = (int) 1e9;
	
	static void write(Point[] p) throws IOException {
		PrintWriter out = new PrintWriter(String.format("%02d", ++testcount));
		System.out.println("Generating test #" + testcount);
		out.println(p.length);
		for (Point pp : p) {
			out.println(pp.x + " " + pp.y);
		}
		out.close();
	}
	
	static Point randPoint(int maxx, int maxy) {
		return new Point(random.nextInt(2 * maxx + 1) - maxx, random.nextInt(2 * maxy + 1) - maxy);
	}
	
	static void writeRand(int n, int maxc) throws IOException {
		Point[] p = new Point[n];
		HashSet<Point> hs = new HashSet<Point>();
		for (int i = 0; i < n; i++) {
			p[i] = randPoint(maxc, maxc);
			while (hs.contains(p[i])) {
				p[i] = randPoint(maxc, maxc);
			}
			hs.add(p[i]);
		}
		write(p);
	}
	
	static void writeLine(int n, int maxc) throws IOException {
		int dx = random.nextInt(2 * maxc / n) + 1;
		int dy = random.nextInt(2 * maxc / n) + 1;
		Point[] p = new Point[n];
		p[0] = randPoint(maxc, maxc);
		int max = Math.min((maxc - p[0].x) / dx, (maxc - p[0].y) / dy);
		int min = -Math.min((p[0].x + maxc) / dx, (p[0].y + maxc) / dy);
		HashSet<Integer> hs = new HashSet<Integer>();
		hs.add(0);
		for (int i = 1; i < n; i++) {
			while (true) {
				int t = random.nextInt(max - min + 1) + min;
				if (hs.contains(t)) continue;
				p[i] = new Point(p[0].x + t * dx, p[0].y + t * dy);
				hs.add(t);
				break;
			}
		}
		write(p);
	}
	
	static void writeH(int n, int maxc) throws IOException {
		int y = random.nextInt(2 * maxc + 1) - maxc;
		Point[] p = new Point[n];
		HashSet<Integer> hs = new HashSet<Integer>();
		for (int i = 0; i < n; i++) {
			int x = random.nextInt(2 * maxc + 1) - maxc;
			while (hs.contains(x)) {
				x = random.nextInt(2 * maxc + 1) - maxc;
			}
			hs.add(x);
			p[i] = new Point(x, y);
		}
		write(p);
	}

	static void writeV(int n, int maxc) throws IOException {
		int x = random.nextInt(2 * maxc + 1) - maxc;
		Point[] p = new Point[n];
		HashSet<Integer> hs = new HashSet<Integer>();
		for (int i = 0; i < n; i++) {
			int y = random.nextInt(2 * maxc + 1) - maxc;
			while (hs.contains(y)) {
				y = random.nextInt(2 * maxc + 1) - maxc;
			}
			hs.add(y);
			p[i] = new Point(x, y);
		}
		write(p);
	}
	
	static void writeAll(int x1, int x2, int y1, int y2) throws IOException {
		ArrayList<Point> p = new ArrayList<Point>();
		for (int i = x1; i <= x2; i++) {
			for (int j = y1; j <= y2; j++) {
				p.add(new Point(i, j));
			}
		}
		Collections.shuffle(p, random);
		Point[] ap = p.toArray(new Point[p.size()]);
		write(ap);
	}

	public static void main(String[] args) throws IOException {
		while (new File(String.format("%02d.t", testcount + 1)).exists()) {
			testcount++;
		}
		writeRand(2, 10);
		writeRand(100, 100);
		writeRand(2000, 100);
		writeLine(4, 20);
		writeLine(564, 4000);
		writeH(7, 30);
		writeV(9, 50);
		writeAll(0, 5, 0, 5);
		for (int i = 0; i < 5; i++) {
			writeRand(1000, 1000);
		}
		writeAll(-150, 150, 45, 345);
		writeLine(MAXN, MAXC);
		writeLine(MAXN, MAXC);
		writeV(MAXN, MAXC);
		writeH(MAXN, MAXC);
		for (int i = 0; i < 5; i++) {
			writeRand(MAXN, MAXC);
		}
	}

}

class Point {
	int x, y;
	
	Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	@Override
	public boolean equals(Object o) {
		Point p = (Point) o;
		return p.x == x && p.y == y;
	}
	
	@Override
	public int hashCode() {
		return x * 239017 + y;
	}
}
