import java.io.*;
import java.math.BigInteger;
import java.util.Random;

public class NumbersTestGen {

    final static Random rnd = new Random(239);

    public static void main(String[] args) {
        new NumbersTestGen().generate();
    }

    PrintWriter out;
    String dirName = "";
    int countTests;

    void generate() {
        new File("../tests.desc").delete();
        this.countTests = 0;
        generateSamples();
        this.countTests = 0;
        generateSubtask1();
        generateSubtask2();
        generateSubtask3();
        generateSubtask4();
    }

    void setDirectory(String name) {
        this.dirName = "../" + name;
        File folder = new File(this.dirName);
        if (!folder.exists()) {
            folder.mkdirs();
        }
    }

    private void generateSamples() {
        setDirectory("preliminary");
        printTest(1, 100, "sample test #1");
    }

    private void generateSubtask1() {
        setDirectory("tests/subtask1");
        printTest(1, 1, "");
        printTest(1, 9, "");
        printTest(1, 1000, "");
        printTest(1, 999, "");
        printTest(1, 99, "");
        printTest(1, 123, "");
        printTest(1, 987, "");
        printTest(1, 605, "minimum digit in the middle");
        printTest(1, 506, "minimum digit in the middle");
        printTest(1, 482, "maximum digit in the middle");
        printTest(1, 284, "maximum digit in the middle");
        for (int i = 0; i < 5; i++) {
            printTest(1, rnd.nextInt(1000) + 1, "random test");
        }
    }


    private void generateSubtask2() {
        setDirectory("tests/subtask2");
        long max = 1000000000000000000L;
        int maxL = (int) (1e+9 + 1);
        printTest(1, max, "");
        printTest(1, max - 1, "");
        printTest(84 * (long) (1e+15), 85 * (long) (1e+15), "answer must be zero");
        long val = 111223344455667899L;
        printTest(rnd.nextInt(maxL) + 1, val, "digits of r increase");
        printTest(val - 5, val + 5, "answer must be one");
        generatePrefixTest(Long.toString(val), 12);
        generatePrefixTest(Long.toString(val), 5);
        printTest(Integer.toString(rnd.nextInt(1000000000) + 1), new StringBuilder(Long.toString(val)).reverse().toString(), "digits of r decrease");
        for (int i = 0; i < 3; i++) {
            printTest(getRandLong(max / 10) + 1, getRandLong(max) + 1, "random test");
        }
    }

    private void generateSubtask3() {
        setDirectory("tests/subtask3");
        generate10PTest(100);
        for (int i = 0; i < 7; i++) {
            generate10PTest(rnd.nextInt(70) + 31);
        }
    }

    private void generateSubtask4() {
        setDirectory("tests/subtask4");
        printTest(BigInteger.ONE, BigInteger.TEN.pow(100).subtract(BigInteger.ONE), "");
//        printTest(BigInteger.TEN.pow(100).subtract(BigInteger.ONE), BigInteger.TEN.pow(100), "");
//        printTest(BigInteger.valueOf(84).multiply(BigInteger.TEN.pow(98)), BigInteger.valueOf(85).multiply(BigInteger.TEN.pow(98)), "answer must be zero");
        BigInteger val = generateRandomIncrease(100);
        printTest(BigInteger.ONE, val, "digits of r increase");
        printTest(val, BigInteger.TEN.pow(100), "digits of l increase");
        printTest(getRandBigInt(50), new BigInteger(new StringBuilder(val.toString()).reverse().toString()), "digits of r decrease");
//        printTest(val.subtract(BigInteger.valueOf(5)), val.add(BigInteger.valueOf(5)), "answer must be one");
        generatePrefixTest(val.toString(), 25);
        generatePrefixTest(val.toString(), 50);
        generatePrefixTest(val.toString(), 90);
        for (int i = 50; i <= 90; i += 20) {
            printTest(getRandBigInt(i), getRandBigInt(100), "random test");
        }
        BigInteger n1 = getRandBigInt(100);
        BigInteger n2 = getRandBigInt(100);
        if (n1.compareTo(n2) > 0) {
            printTest(n2, n1, "random test");
        } else {
            printTest(n1, n2, "random test");
        }

    }

    private BigInteger getRandBigInt(int len) {
        String str = "";
        for (int i = 0; i < len; i++) {
            str += rnd.nextInt(10);
        }
        return new BigInteger(str);
    }

    private BigInteger generateRandomIncrease(int len) {
        int[] sum = new int[10];
        for (int i = 0; i < len; i++) {
            sum[rnd.nextInt(9) + 1]++;
        }
        String str = "";
        for (int i = 1; i < sum.length; i++) {
            for (int j = 0; j < sum[i]; j++) {
                str += i;
            }
        }
        return new BigInteger(str);
    }

    private void generate10PTest(int len) {
        printTest(BigInteger.ONE, BigInteger.TEN.pow(len), "r = 10^" + len);
    }

    private long getRandLong(long border) {
        long res = rnd.nextLong();
        res = res % border;
        res = res + border;
        res = res % border;
        return res;
    }

    private void generatePrefixTest(String val, int lenPrefix) {
        String res = val.substring(0, lenPrefix);
        while (res.length() < val.length()) {
            res += rnd.nextInt(10);
        }
        printTest(Integer.toString(rnd.nextInt((int) (1e+9)) + 1), res, "incr in " + lenPrefix + " prefix of r");
    }


    void printTest(long l, long r, String desc) {
        printTest(Long.toString(l), Long.toString(r), desc);
    }

    void printTest(BigInteger l, BigInteger r, String desc) {
        printTest(l.toString(), r.toString(), desc);
    }


    void printTest(String l, String r, String desc) {
        try {
            countTests++;
            String fileName = dirName + "/";
            fileName += String.format("%02d", countTests);
            out = new PrintWriter(fileName);
            out.println(l);
            out.println(r);
            appendDescription(fileName, "l" + compress(l) + " r" + compress(r) + " " + desc);
            System.out.println("Done printing test " + fileName.substring(3));
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    String compress(String s) {
        if (s.length() < 10) {
            return " = " + s;
        }
        return " has " + s.length() + " digits";
    }

    private void appendDescription(String fileName, String desc) {
        try (FileWriter fw = new FileWriter("../tests.desc", true);
             PrintWriter out = new PrintWriter(fw)) {
            out.println(fileName + "   " + desc);
        } catch (IOException e) {
            System.err.println("Could not append test description");
        }
    }
}
