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

public class TestGen {

	PrintWriter out;
	Random rnd;
	int tNumber;

	class Test {
		char[] string;
		char[] replaces;

		void printTest() throws IOException {
			if (tNumber < 10)
				out = new PrintWriter("../tests/0" + tNumber);
			else
				out = new PrintWriter("../tests/" + tNumber);
			tNumber++;

			out.println(new String(string));

			int cnt = 0;
			for (int i = 0; i < 26; i++) {
				if (replaces[i] != 0) {
					cnt++;
				}
			}
			out.println(cnt);

			ArrayList<Integer> order = new ArrayList<Integer>();
			for (int i = 0; i < 26; i++) {
				order.add(i);
			}
			if (tNumber != 4) {
				Collections.shuffle(order, rnd);
			}

			for (int x : order) {
				if (replaces[x] != 0) {
					out.println((char) (x + 'a') + " " + replaces[x]);
				}
			}

			out.close();
		}

		void genPalindromicalTest(int l, int x) throws IOException {
			string = new char[l];
			for (int i = 0; i < string.length; i++) {
				if (string[string.length - i - 1] != 0)
					string[i] = string[string.length - i - 1];
				else
					string[i] = (char) (rnd.nextInt(26) + 'a');
				if ((rnd.nextDouble() < 0.1) && (x > 0)) {
					string[i] = (char) (rnd.nextInt(26) + 'a');
					x--;
				}
			}

			replaces = new char[26];
			for (int i = 0; i < 26; i++) {
				if (rnd.nextBoolean()) {
					replaces[i] = (char) (rnd.nextInt(26) + 'a');
				}
			}

		}

		void genRandomTest(int l, int x, int y) throws IOException {
			string = new char[l];
			replaces = new char[26];
			char[] back = new char[26];
			for (int i = 0; i < y; i++) {
				char z = (char) rnd.nextInt(26);
				while (replaces[z] != 0) {
					z = (char) rnd.nextInt(26);
				}
				replaces[z] = (char) (rnd.nextInt(26) + 'a');
				if (rnd.nextBoolean())
					replaces[z] = (char) (z + 'a');
				if (replaces[z] != 0) {
					back[replaces[z] - 'a'] = (char) (z + 'a');
				}
			}
			// System.err.println(Arrays.toString(replaces));
			// System.err.println(Arrays.toString(back));
			for (int i = 0; i < l; i++) {
				if (string[string.length - i - 1] != 0)
					string[i] = string[string.length - i - 1];
				else
					string[i] = (char) (rnd.nextInt(26) + 'a');
				if ((rnd.nextDouble() < 0.3) && (x > 0)) {
					string[i] = (char) (rnd.nextInt(26) + 'a');
					x--;
					// System.err.println(":)");
				}
				// System.err.println(Arrays.toString(string));
				if (rnd.nextBoolean() && (back[string[i] - 'a'] != 0)) {
					string[i] = (char) (back[string[i] - 'a']);
				}
			}
			printTest();
		}

		void genAllReplacesTest(int l, int x, int y) throws IOException {
			int[] pair = new int[26];
			Arrays.fill(pair, -1);

			replaces = new char[26];

			for (int i = 0; i < 26; i++) {
				if (pair[i] >= 0)
					continue;
				int t = rnd.nextInt(26);
				while (pair[t] != -1)
					t = rnd.nextInt(26);
				pair[i] = t;
				pair[t] = i;
				char z = (char) (rnd.nextInt(26) + 'a');
				replaces[i] = z;
				replaces[t] = z;
			}

			string = new char[l];
			for (int i = 0; i < l / 2; i++) {
				string[i] = (char) (rnd.nextInt(26) + 'a');
				string[l - i - 1] = (char) (pair[string[i] - 'a'] + 'a');
				if ((rnd.nextDouble() < 0.1) && (y > 0)) {
					y--;
					string[l - i - 1] = string[i];
				}
				if ((rnd.nextDouble() < 0.1) && (x > 0)) {
					string[i] = (char) (rnd.nextInt(26) + 'a');
					x--;
				}
				if ((rnd.nextDouble() < 0.1) && (x > 0)) {
					string[l - i - 1] = (char) (rnd.nextInt(26) + 'a');
					x--;
				}
			}
			if (l % 2 != 0)
				string[l / 2] = (char) (rnd.nextInt(26) + 'a');
			printTest();
		}

		public void genSampleOne() throws IOException {
			string = new char[] { 'a', 'b', 'c' };
			replaces = new char[26];
			replaces['a' - 'a'] = 'c';
			printTest();
		}

		public void genSampleTwo() throws IOException {
			string = new char[] { 'a', 'b', 'c' };
			replaces = new char[26];
			replaces['b' - 'a'] = 'c';
			printTest();
		}

		public void genSampleThree() throws IOException {
			string = new char[] { 'a', 'b', 'c' };
			replaces = new char[26];
			replaces['c' - 'a'] = 'd';
			replaces['d' - 'a'] = 'a';
			printTest();
		}

	}

	public void solve() throws IOException {
		tNumber = 1;
		rnd = new Random(31);

		Test t = new Test();

		t.genSampleOne();
		t.genSampleTwo();
		t.genSampleThree();

		t.genRandomTest(1, 0, 5);
		t.genRandomTest(1, 0, 0);
		t.genRandomTest(12, 1, 1);
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				for (int k = 0; k < 2; k++) {
					t.genRandomTest(15 + i, 5 + j, 2 + k);
				}
			}
		}

		t.genRandomTest(100, 5, 5);
		t.genRandomTest(100000, 0, 26);
		t.genRandomTest(100000, 26, 26);

		t.genPalindromicalTest(2, 0);
		t.genPalindromicalTest(2, 1);
		t.genPalindromicalTest(15, 0);
		t.genPalindromicalTest(15, 1);
		t.genPalindromicalTest(99, 0);
		t.genPalindromicalTest(100, 1);
		t.genPalindromicalTest(99999, 0);
		t.genPalindromicalTest(100000, 1);

		t.genAllReplacesTest(99, 1, 0);
		t.genAllReplacesTest(99999, 5, 5);
		t.genAllReplacesTest(100000, 1, 1);
		t.genAllReplacesTest(100000, 0, 0);

	}

	public void run() {
		try {

			solve();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

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