// Tests generator for Collider2 problem
// Author : Vladimir Ulyantsev, ulyantsev@rain.ifmo.ru

import java.awt.Point;
import java.io.*;
import java.util.*;

public class ColliderTestsGen implements Runnable {
    public static void main(String[] args) {
        if (args.length < 1) {
        	for (I = 1; (new File(getName(I) + ".t")).exists(); I++);
        } else {
            I = Integer.parseInt(args[0]);
        }
        new Thread(new ColliderTestsGen()).start();
    }

    PrintWriter out;

    Random random = new Random(6466403L);

    static int I;

    static String getName(int i) {
    	return ((i < 10) ? "0" : "") + i;
    }
    
    void open() {
        try {
        	System.out.println("Generating test " + I);
            out = new PrintWriter(getName(I));
        } catch (FileNotFoundException e) {        	
        	e.printStackTrace();
        	System.exit(-1);
        }
    }

    void close() {
        out.close();
        I++;
    }

	Point rotateCl(Point o, Point p) {
		return new Point(o.x + p.y - o.y, o.y - p.x + o.x);
	}

	Point rotateOvCl(Point o, Point p) {
		return new Point(o.x - p.y + o.y, o.y + p.x - o.x);
	}

    
    void genLittle(int n) {
    	open();
    	int litx = 10;
    	ArrayList<Point> pt = new ArrayList<Point>();
    	for (int i = 0; i < n; i++) {
    		int x = random.nextInt(2 * litx + 1) - litx;
    		int y = random.nextInt(2 * litx + 1) - litx;
    		while (pt.contains(new Point(x, y))) {
    			x = random.nextInt(2 * litx + 1) - litx;
        		y = random.nextInt(2 * litx + 1) - litx;
    		}
    		pt.add(new Point(x, y));
    	}
    	
    	out.println(n);
    	for (Point p : pt) {
    		out.println(p.x + " " + p.y);
    	}
    	close();
    }
    
    void genRand(int n) {
    	open();
    	int litx = 100000000;
    	ArrayList<Point> pt = new ArrayList<Point>();
    	for (int i = 0; i < n; i++) {
    		int x = random.nextInt(2 * litx + 1) - litx;
    		int y = random.nextInt(2 * litx + 1) - litx;
    		while (pt.contains(new Point(x, y))) {
    			x = random.nextInt(2 * litx + 1) - litx;
        		y = random.nextInt(2 * litx + 1) - litx;
    		}
    		pt.add(new Point(x, y));
    	}
    	
    	out.println(n);
    	for (Point p : pt) {
    		out.println(p.x + " " + p.y);
    	}
    	close();
    }

    void genRand1(int n) {
    	open();
    	int litx = 100000000;
    	ArrayList<Point> pt = new ArrayList<Point>();
    	for (int i = 0; i < n - 1; i++) {
    		int x = random.nextInt(2 * litx + 1) - litx;
    		int y = random.nextInt(2 * litx + 1) - litx;
    		while (pt.contains(new Point(x, y))) {
    			x = random.nextInt(2 * litx + 1) - litx;
        		y = random.nextInt(2 * litx + 1) - litx;
    		}
    		pt.add(new Point(x, y));
    	}
    	
    	int i = random.nextInt(n - 1);
    	int j = random.nextInt(n - 1);
    	Point p1 = rotateCl(pt.get(i), pt.get(j));
    	while (i == j || !(-litx <= p1.x && p1.x <= litx && -litx <= p1.y && p1.y <= litx)) {
    		i = random.nextInt(n - 1);
        	j = random.nextInt(n - 1);
        	p1 = rotateCl(pt.get(i), pt.get(j));
    	}
    	pt.add(n / 2, p1);
    	
    	out.println(n);
    	for (Point p : pt) {
    		out.println(p.x + " " + p.y);
    	}
    	close();
    }
    
    void genRand0(int n) {
    	open();
    	int litx = 100000000;
    	ArrayList<Point> pt = new ArrayList<Point>();
    	for (int i = 0; i < n - 3; i++) {
    		int x = random.nextInt(2 * litx + 1) - litx;
    		int y = random.nextInt(2 * litx + 1) - litx;
    		while (pt.contains(new Point(x, y))) {
    			x = random.nextInt(2 * litx + 1) - litx;
        		y = random.nextInt(2 * litx + 1) - litx;
    		}
    		pt.add(new Point(x, y));
    	}
    	
    	int i = n / 2 + random.nextInt(10);
    	int j = n / 2 + random.nextInt(10);
    	Point p1 = rotateCl(pt.get(i), pt.get(j));
		Point p2 = rotateOvCl(pt.get(j), pt.get(i));
    	while (i == j || !(-litx <= p1.x && p1.x <= litx && -litx <= p1.y && p1.y <= litx
    			 && -litx <= p2.x && p2.x <= litx && -litx <= p2.y && p2.y <= litx)) {
    		i = n / 2 + random.nextInt(10);
        	j = n / 2 + random.nextInt(10);
        	p1 = rotateCl(pt.get(i), pt.get(j));
    		p2 = rotateOvCl(pt.get(j), pt.get(i));
    	}
    	pt.add(n / 2, p1);
	pt.add(n / 2 + 10, p2);
    	
	i = n / 2 - random.nextInt(10);
    	j = n / 2 - random.nextInt(10);
    	p1 = rotateCl(pt.get(i), pt.get(j));
    	while (i == j || !(-litx <= p1.x && p1.x <= litx && -litx <= p1.y && p1.y <= litx)) {
    		i = n / 2 - random.nextInt(10);
        	j = n / 2 - random.nextInt(10);
    		p1 = rotateCl(pt.get(i), pt.get(j));
    	}
    	pt.add(n / 2, p1);
		
    	out.println(n);
    	for (Point p : pt) {
    		out.println(p.x + " " + p.y);
    	}
    	close();
    }
    
    public void solve() throws IOException {
		for (int i = 0; i < 10; i++) {
			genLittle(1 + random.nextInt(100));						
		}
		
		for (int i = 0; i < 7; i++) {
			genRand(200);						
		}
		for (int i = 0; i < 6; i++) {
			genRand1(200);						
		}
		for (int i = 0; i < 7; i++) {
			genRand0(200);						
		}
		
		for (int i = 0; i < 6; i++) {
			genRand(2000);						
		}
		for (int i = 0; i < 7; i++) {
			genRand1(2000);						
		}
		for (int i = 0; i < 7; i++) {
			genRand0(2000);						
		}
    }

    public void run() {
        try {
            solve();
        } catch (Throwable e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
}
