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

public class TestsGen {
	static int testcount = 0;

	static Random random = new Random(36498732);
	
	static int maxn = 100;
	
	static int maxk = 1000;

	static void write(int[][] a, int k) throws IOException {
		PrintWriter out = new PrintWriter(String.format("%02d", ++testcount));
		System.out.println("Generating test #" + testcount);
		out.println(a.length + " " + a[0].length);
		out.println(k);
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				if (j > 0) {
					out.print(" ");
				}
				out.print(a[i][j]);
			}
			out.println();
		}
		out.close();
	}
	
	static int[][] fill(int n, int m, int k, int par) {
		int[][] ret = new int[n][m];
		ArrayList<Integer> cols = new ArrayList<Integer>();
		for (int i = 0; i < n * m / k; i++) {
			cols.add(i + 1);
		}
		Collections.shuffle(cols, random);
		int dir = 1;
		int x = 0;
		int y = 0;
		if (par == 2) {
			x = n - 1;
			dir = -1;
		}
		if (par == 3) {
			y = m - 1;
			dir = -1;
		}
		int nc = 0;
		int c = 0;
		for (int i = 0; i < n * m; i++) {
			ret[x][y] = cols.get(nc);
			c++;
			if (c == k) {
				nc++;
				c = 0;
			}
			if (par % 2 == 0) {
				x += dir;
				if (x == n) {
					y++;
					x--;
					dir = -dir;
				}
				if (x < 0) {
					y++;
					x++;
					dir = -dir;
				}
			} else {
				y += dir;
				if (y == m) {
					y--;
					x++;
					dir = -dir;
				}
				if (y < 0) {
					y++;
					x++;
					dir = -dir;
				}
			}
		}
		return ret;
	}
	
	static void writeGood(int n, int m) throws IOException {
		ArrayList<Integer> divs = getDivs(n * m);
		int k = divs.get(random.nextInt(divs.size()));
		while (k > maxk) {
			k = divs.get(random.nextInt(divs.size()));
		}
		int[][] a = fill(n, m, k, random.nextInt(4));
		write(a, k);
	}

	static void writeAlmostGood(int n, int m) throws IOException {
		ArrayList<Integer> divs = getDivs(n * m);
		int k = divs.get(random.nextInt(divs.size()));
		while (k == n * m || k > maxk) {
			k = divs.get(random.nextInt(divs.size()));
		}
		int[][] a = fill(n, m, k, random.nextInt(4));
		int x1 = random.nextInt(n);
		int y1 = random.nextInt(m);
		int x2 = random.nextInt(n);
		int y2 = random.nextInt(m);
		while (a[x1][y1] == a[x2][y2]) {
			x1 = random.nextInt(n);
			y1 = random.nextInt(m);
			x2 = random.nextInt(n);
			y2 = random.nextInt(m);
		}
		int t = a[x1][y1];
		a[x1][y1] = a[x2][y2];
		a[x2][y2] = t;
		write(a, k);
	}

	static void writeAlmostGood2(int n, int m) throws IOException {
		ArrayList<Integer> divs = getDivs(n * m);
		int k = divs.get(random.nextInt(divs.size()));
		while (k > maxk) {
			k = divs.get(random.nextInt(divs.size()));
		}
		int[][] a = fill(n, m, k, random.nextInt(4));
		int x1 = random.nextInt(n);
		int y1 = random.nextInt(m);
		a[x1][y1] = random.nextInt(n * m / k) + 1;
		write(a, k);
	}

	private static ArrayList<Integer> getDivs(int n) {
		ArrayList<Integer> ret = new ArrayList<Integer>();
		for (int i = 1; i <= n; i++) {
			if (n % i == 0) {
				ret.add(i);
			}
		}
		return ret;
	}

	public static void main(String[] args) throws IOException {
		while (new File(String.format("%02d.t", testcount + 1)).exists()) {
			testcount++;
		}
		writeGood(10, 10);
		writeGood(6, 15);
		writeAlmostGood(3, 4);
		writeAlmostGood2(5, 4);
		for (int i = 0; i < 10; i++) {
			writeGood(random.nextInt(maxn) + 1, random.nextInt(maxn) + 1);
			writeAlmostGood(random.nextInt(maxn) + 1, random.nextInt(maxn) + 1);
			writeAlmostGood2(random.nextInt(maxn) + 1, random.nextInt(maxn) + 1);
		}
	}

}
