import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Random;

public class TestGen {
	public static void main(String[] args) {
		new TestGen().run();
	}

	int BOUNDS = (int) 1e3;

	private void run() {
		for (int i = 0; i < 5; i++) {
			genInRound(5 + rand.nextInt(11));
		}
		for (int i = 0; i < 5; i++) {
			genInRound(10 + rand.nextInt(91));
		}
		genInRound(100);
		for (int i = 0; i < 5; i++) {
			genInSquare(10 + rand.nextInt(91));
		}
		genInSquare(100);
		for (int i = 0; i < 5; i++) {
			genInRandomRect(10 + rand.nextInt(91));
		}
		genInRandomRect(100);
		for (int i = 0; i < 5; i++) {
			genInRandomRound(10 + rand.nextInt(91));
		}
		genInRandomRound(100);
		genParabola(100);
		genCircle(100);
		for (int i = 0; i < 5; i++) {
			genParabola(50 + rand.nextInt(51));
		}
	}

	private void genCircle(int n) {
		Point[] p = new Point[n];
		for (int i = 0; i < p.length; i++) {
			double al = i * 2 * Math.PI / p.length;
			p[i] = new Point(BOUNDS * Math.cos(al), BOUNDS * Math.sin(al));
		}
		// debug = true;
		writeTest(p);
		debug = false;
	}

	boolean debug = false;

	private void genInRandomRound(int n) {
		int x = BOUNDS / 2 - rand.nextInt(BOUNDS + 1);
		int y = BOUNDS / 2 - rand.nextInt(BOUNDS + 1);
		int R = 1 + rand.nextInt(BOUNDS / 2);
		Point[] p = new Point[n];
		for (int i = 0; i < p.length; i++) {
			double r = rand.nextInt(R) + rand.nextDouble();
			double al = rand.nextDouble() * 2 * Math.PI;
			p[i] = new Point(x + r * Math.cos(al), y + r * Math.sin(al));
		}
		writeTest(p);
	}

	private void genInRandomRect(int n) {
		int x1 = BOUNDS - rand.nextInt(2 * BOUNDS + 1);
		int x2 = BOUNDS - rand.nextInt(2 * BOUNDS + 1);
		int y1 = BOUNDS - rand.nextInt(2 * BOUNDS + 1);
		int y2 = BOUNDS - rand.nextInt(2 * BOUNDS + 1);
		if (x1 == x2 || y1 == y2) {
			return;
		}
		if (x1 > x2) {
			int tmp = x1;
			x1 = x2;
			x2 = tmp;
		}
		if (y1 > y2) {
			int tmp = y1;
			y1 = y2;
			y2 = tmp;
		}
		Point[] p = new Point[n];
		for (int i = 0; i < p.length; i++) {
			double x = x1 + rand.nextInt(x2 - x1 + 1);
			double y = y1 + rand.nextInt(y2 - y1 + 1);
			p[i] = new Point(x, y);
		}
		writeTest(p);
	}

	private void genParabola(int n) {
		if (n % 2 != 0) {
			n++;
		}
		Point[] p = new Point[n];
		int k = 0;
		for (int i = -n / 2 + 1; i < n / 2; i++) {
			double x = BOUNDS / n * i;
			double y = 0.80 * i * i - BOUNDS;
			p[k++] = new Point(x, y);
		}
		p[n - 1] = new Point(0, 0.8 * n * n / 4 - BOUNDS);
		writeTest(p);
	}

	private void genInSquare(int n) {
		Point[] p = new Point[n];
		for (int i = 0; i < p.length; i++) {
			double x = BOUNDS - rand.nextInt(2 * BOUNDS + 1);
			double y = BOUNDS - rand.nextInt(2 * BOUNDS + 1);
			p[i] = new Point(x, y);
		}
		writeTest(p);
	}

	Random rand = new Random(341562362);

	private void genInRound(int n) {
		Point[] p = new Point[n];
		for (int i = 0; i < p.length; i++) {
			double r = rand.nextInt(BOUNDS) + rand.nextDouble();
			double al = rand.nextDouble() * 2 * Math.PI;
			p[i] = new Point(r * Math.cos(al), r * Math.sin(al));
		}
		writeTest(p);
	}

	int test = 2;

	void writeTest(Point[] points) {
		int turn = rand.nextInt(4);
		int swap = rand.nextInt(2);
		for (Point p : points) {
			if (swap == 1) {
				long tmp = p.x;
				p.x = p.y;
				p.y = tmp;
			}
			for (int i = 0; i < turn; i++) {
				long x = -p.y;
				long y = p.x;
				p.x = x;
				p.y = y;
			}
		}
		points = convexHull(points);
		{
			long s = 0;
			for (int i = 0; i < points.length; i++) {
				int j = (i + 1) % points.length;
				s += points[i].x * points[j].y - points[j].x * points[i].y;
			}
			if (s < 0) {
				for (int i = 0, j = points.length - 1; i < j; i++, j--) {
					Point tmp = points[i];
					points[i] = points[j];
					points[j] = tmp;
				}
			}
		}
		test++;
		System.out.println(test);
		if (debug) {
			System.out.println(points.length + " " + test);
		}
		try {
			PrintWriter out = new PrintWriter((test / 10) + "" + (test % 10));
			out.println(points.length);
			int s = rand.nextInt(points.length);
			for (int i = 0; i < points.length; i++) {
				Point p = points[(s + i) % points.length];
				out.println(p.x + " " + p.y);
			}
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class Point implements Comparable<Point> {
		long x, y;
		double al;

		public Point(double d, double e) {
			x = Math.round(d);
			y = Math.round(e);
		}

		public void setAngle(Point p) {
			if (x == p.x && y == p.y) {
				al = Double.NEGATIVE_INFINITY;
				return;
			}
			al = Math.atan2(y - p.y, x - p.x);
		}

		@Override
		public int compareTo(Point p) {
			return (int) Math.signum(al - p.al);
		}
	}

	Point[] convexHull(Point[] points) {
		Point ld = points[0];
		for (int i = 0; i < points.length; i++) {
			if (points[i].x < ld.x
					|| (points[i].x == ld.x && points[i].y < ld.y)) {
				ld = points[i];
			}
		}
		for (int i = 0; i < points.length; i++) {
			points[i].setAngle(ld);
		}
		Arrays.sort(points);
		if (debug) {
			System.out.println("After sort: ");
			for (Point p : points) {
				System.out.println(p.x + " " + p.y);
			}
		}
		Point[] stack = new Point[points.length];
		int top = 0;
		loop: for (Point p : points) {
			if (debug) {
				System.out.println(top);
			}
			while (top > 1) {
				Point pa = stack[top - 2];
				Point pb = stack[top - 1];
				long dx1 = pb.x - pa.x;
				long dy1 = pb.y - pa.y;
				long dx2 = p.x - pa.x;
				long dy2 = p.y - pa.y;
				if (dx1 * dy2 - dx2 * dy1 == 0) {
					if (dx1 * dx1 + dy1 * dy1 >= dx2 * dx2 + dy2 * dy2) {
						continue loop;
					}
				}
				long s = pa.x * pb.y - pa.x * p.y + pb.x * p.y - pb.x * pa.y
						+ p.x * pa.y - p.x * pb.y;
				if (s <= 0) {
					top--;
				} else {
					break;
				}
			}
			stack[top++] = p;
		}
		if (debug) {
			System.out.println(top);
		}
		Point[] ans = new Point[top];
		for (int i = 0; i < ans.length; i++) {
			ans[i] = stack[i];
		}
		return ans;
	}
}
