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

public class Tests {
    static int MAX = 1_000_000_000;
    static int[] MAXN = { 3, 500, 100000, 1000, 300000};
    static int[] MAXA = {10, 100,    100,  MAX,    MAX};
    int group;

    Random rnd = new Random(3289214075201L);

    String folder;

    PrintWriter desc;

    public static void main(String[] args) throws FileNotFoundException {
        new Tests().gen();
    }

    public int random(int l, int r) {
        if (r < l)
            return l;

        return l + rnd.nextInt(r - l + 1);
    }

    static int tests = 1;

    public void writeTest(int[] a, String description) {
        try {
            PrintWriter out = new PrintWriter(String.format(folder + "%02d", tests++));

            System.err.println("Writing test " + (tests - 1));

            desc.println(String.format(folder + "%02d", tests - 1) + "\t" + description + " n = " + a.length);

            out.println(a.length);

            for (int i = 0; i < a.length; i++) {
                out.print(a[i]);
                if (i < a.length - 1) {
                    out.print(" ");
                }
            }
            out.println();

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

    public void genRandom(int n, int from, int to) {
        int[] a = new int[n];
        for (int i = 0; i < a.length; i++) {
            a[i] = random(from, to);
        }
        writeTest(a, "Random test (from = " + from + ", to = " + to + ") with");
    }

    public void genZeros(int n) {
        int[] a = new int[n];
        writeTest(a, "All zeros test with");
    }

    public void genCorrect(int n, int max) {
        int x, y;
        while (true) {
            x = random(-max, max);
            y = random(-max, max);
            if (Math.abs(y - x) <= max) {
                break;
            }
        }
        int[] a = new int[n];
        a[0] = x;
        a[1] = y;
        for (int i = 2; i < n; i++) {
            a[i] = a[i - 1] - a[i - 2];
        }
        writeTest(a, "Harmonic sequence test (max = " + max + ") with");
    }

    public void genSpoilt(int n, int max, int shiftL, int shiftR) {
        int x, y;
        while (true) {
            x = random(-max, max);
            y = random(-max, max);
            if (Math.abs(y - x) <= max) {
                break;
            }
        }
        int[] a = new int[n];
        a[0] = x;
        a[1] = y;
        for (int i = 2; i < n; i++) {
            a[i] = a[i - 1] - a[i - 2];
        }
        for (int i = 0; i < n; i++) {
            a[i] += random(shiftL, shiftR);
        }
        writeTest(a, "Spoilt harmonic sequence test (max = " + max + ", shift in [" + shiftL + ", " + shiftR + "]) with");
    }

    public void genSpoiltMod3(int n, int max, int shiftL0, int shiftR0, int shiftL1, int shiftR1, int shiftL2, int shiftR2) {
        int x, y;
        while (true) {
            x = random(-max, max);
            y = random(-max, max);
            if (Math.abs(y - x) <= max) {
                break;
            }
        }
        int[] a = new int[n];
        a[0] = x;
        a[1] = y;
        for (int i = 2; i < n; i++) {
            a[i] = a[i - 1] - a[i - 2];
        }
        for (int i = 0; i < n; i++) {
            if (i % 3 == 0)
                a[i] += random(shiftL0, shiftR0);
            if (i % 3 == 1)
                a[i] += random(shiftL1, shiftR1);
            if (i % 3 == 2)                   
                a[i] += random(shiftL2, shiftR2);
        }
        writeTest(a, "Spoilt harmonic sequence test (max = " + max + ", shifts depend on i mod 3) with");
    }

    public void genMaxWithSigns(int n, int max, int s1, int s2) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            if (i % 2 == 0) {
                a[i] = max * s1;
            } else {
                a[i] = max * s2;
            }
        }
        writeTest(a, "Maximal test (max = " + max + "; " + s1 + " " + s2 + " ...) with");
    }

    public void gen() {
        try{
            desc = new PrintWriter("../tests.desc");
        } catch (IOException e) {
//
        }

        tests = 1;
        folder = "../preliminary/";
        if (!new File(folder).exists())
            new File(folder).mkdir();
        writeTest(new int[]{1, 2, 0, 0}, "Sample test");

        tests = 1;
        folder = "../tests/";
        if (!new File(folder).exists())
            new File(folder).mkdir();

        for (group = 0; group < MAXN.length; group++) {
            folder = String.format("../tests/subtask%d/", (group + 1));
            if (!new File(folder).exists())
                new File(folder).mkdir();

            int n = MAXN[group];
            int a = MAXA[group];
            int l = Math.max(3, n / 10 * 9);

            genRandom(random(l, n), -a, a);
            genZeros(n);
            genCorrect(random(l, n), a);
            genSpoilt(random(l, n), a / 5 * 4, 0, a / 5);
            genSpoilt(random(l, n), a / 5 * 4, -a / 5, a / 5);
            int newN = Math.max(3, (n + 1) / 3 * 3 - 1);
            genMaxWithSigns(newN, a, 1, -1);
            genMaxWithSigns(newN, a, -1, 1);
            genMaxWithSigns(n, a, 1, 1);
            genMaxWithSigns(n, a, 1, 1);
            genSpoiltMod3(n, a / 5 * 4, -a / 5, a / 5, -a / 5, a / 5, 0, 0);
            genSpoiltMod3(n, a / 5 * 4, -a / 5, a / 5, -a / 5, a / 5, -a / n, a / n);
            int n_m6_3 = Math.max(3, (n - 3) / 6 * 6 + 3);
            genSpoiltMod3(n_m6_3, a / 5 * 4, -a / 5, a / 5, 0, 0, -a / 5, a / 5);
            genSpoiltMod3(n_m6_3, a / 5 * 4, 0, 0, -a / 5, a / 5, -a / 5, a / 5);
            genRandom(random(l, n), -a, 0);
            genRandom(random(l, n), a / 5 * 4, a);
        }

        desc.close();
    }
}
