import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

public class Gen {
    class Problem {
        int start, time, cost;

        Problem(int start, int time, int cost) {
            this.start = start;
            this.time = time;
            this.cost = cost;
        }
    }

    class Test {
        ArrayList<Problem> ps;

        Test() {
            ps = new ArrayList<Problem>();
        }

        Test(ArrayList<Problem> ps) {
            this.ps = ps;
        }
    }

    int testCount = 0;

    void write(Test t) throws IOException {
        PrintWriter out = new PrintWriter(String.format(Locale.US, "../tests/%02d", ++testCount));
        out.println(t.ps.size());
        Collections.shuffle(t.ps, rand);
        for (Problem p : t.ps) {
            out.println(p.start + " " + p.time + " " + p.cost);
        }
        out.close();
    }

    Random rand = new Random(1);

    Problem randProblem(int maxTime, CostProducer costProducer) {
        int start = rand.nextInt(maxTime - 1) + 1;
        int time = rand.nextInt(maxTime - start) + 1;
        int cost = costProducer.getCost();
        return new Problem(start, time, cost);
    }


    Test randomTest(int n, int maxTime, CostProducer costProducer) {
        System.err.println("randomTest n = " + n + " maxtime = " + maxTime + " costProducer = " + costProducer);
        ArrayList<Problem> al = new ArrayList<Problem>();
        for (int i = 0; i < n; i++) {
            al.add(randProblem(maxTime, costProducer));
        }
        return new Test(al);
    }

    Test genStairs(int n) {
        return null;
    }

    Test genEquals(int n, int maxTime) {
        ArrayList<Problem> al = new ArrayList<Problem>();
        for (int i = 0; i < n; i++) {
            int start = rand.nextInt(maxTime - 1) + 1;
            int time = rand.nextInt(maxTime - start) + 1;
            al.add(new Problem(start, time, time));
        }
        return new Test(al);
    }

    interface CostProducer {
        int getCost();
    }

    Test getLargeNumberOfTasks(int n, int maxTime, CostProducer costProducer) {
        System.err.println("getLargeNumberOfTasks n = " + n + " maxtime = " + maxTime + " costProducer = " + costProducer);
        TreeSet<Integer> xs = new TreeSet<Integer>();
        while (xs.size() < n) {
            xs.add(rand.nextInt(maxTime + 1) + 1);
        }
        ArrayList<Integer> ts = new ArrayList<Integer>(xs);
        Collections.sort(ts);
        ArrayList<Problem> al = new ArrayList<Problem>();
        int i = 0;
        while (i + 1 < ts.size() && al.size() < n / 2) {
            int from = ts.get(i);
            int to = ts.get(i + 1);
            al.add(new Problem(from, to - from, costProducer.getCost()));
            i += 1 + rand.nextInt(2);
        }
        while (al.size() < n) {
            int a = ts.get(rand.nextInt(ts.size()));
            int b = a;
            while (a == b) {
                b = ts.get(rand.nextInt(ts.size()));
            }
            int from = Math.min(a, b);
            int to = Math.max(a, b);
            al.add(new Problem(from, to - from, costProducer.getCost()));
        }
        return new Test(al);
    }


    Test getFewDifferentTimes(int n, int maxTime, CostProducer costProducer) {
        System.err.println("getFewDifferentTimes n = " + n + " maxtime = " + maxTime + " costProducer = " + costProducer);
        TreeSet<Integer> xs = new TreeSet<Integer>();
        while (xs.size() < Math.min(maxTime * 0.95, 5 * Math.sqrt(n))) {
            xs.add(rand.nextInt(maxTime + 1) + 1);
        }
        ArrayList<Integer> ts = new ArrayList<Integer>(xs);
        Collections.sort(ts);
        ArrayList<Problem> al = new ArrayList<Problem>();
        int i = 0;
        while (al.size() < n) {
            int a = ts.get(rand.nextInt(ts.size()));
            int b = a;
            while (a == b) {
                b = ts.get(rand.nextInt(ts.size()));
            }
            int from = Math.min(a, b);
            int to = Math.max(a, b);
            al.add(new Problem(from, to - from, costProducer.getCost()));
        }
        return new Test(al);
    }

    class RandomCostProducer implements CostProducer {
        int maxCost;

        RandomCostProducer(int maxCost) {
            this.maxCost = maxCost;
        }

        @Override
        public int getCost() {
            return rand.nextInt(maxCost) + 1;
        }

        @Override
        public String toString() {
            return "RandomCostProducer{" +
                    "maxCost=" + maxCost +
                    '}';
        }
    }

    class EqualsCostProducer implements CostProducer {
        int cost;

        EqualsCostProducer(int cost) {
            this.cost = cost;
        }

        @Override
        public int getCost() {
            return cost;
        }

        @Override
        public String toString() {
            return "EqualsCostProducer{" +
                    "cost=" + cost +
                    '}';
        }
    }


    class IntervalCostProducer implements CostProducer {
        int a, b;

        IntervalCostProducer(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int getCost() {
            return a + rand.nextInt(b - a + 1);
        }

        @Override
        public String toString() {
            return "IntervalCostProducer{" +
                    "a=" + a +
                    ", b=" + b +
                    '}';
        }
    }

    int MAXT = (int) 1e9;
    int MAXCOST = (int) 1e9;
    int MAXCOST2 = (int) 1e6;
    int MAXN = (int) 1e5;
    int MAXN2 = (int) 1e3;
    int MAXT2 = (int) 1e5;

    CostProducer randomEq(int x) {
        return new EqualsCostProducer(rand.nextInt(x) + 1);
    }

    CostProducer randomEqInt(int a, int b) {
        return new EqualsCostProducer(a + rand.nextInt(b - a + 1));
    }

    void writeSamples() throws IOException {
        PrintWriter out = new PrintWriter(String.format(Locale.US, "../preliminary/01"));
        out.println("2");
        out.println("1 1 1");
        out.println("2 2 2");
        out.close();

        out = new PrintWriter(String.format(Locale.US, "../preliminary/02"));
        out.println("3");
        out.println("1 2 1");
        out.println("3 2 1");
        out.println("2 4 3");
        out.close();
    }


    void run() throws IOException {
        writeSamples();
        // N<=1000, C=const, 15 tests
        write(randomTest(5, 5, randomEq(10)));
        write(randomTest(10, 10, randomEq(10)));
        write(randomTest(15, 15, randomEq(10)));
        write(randomTest(30, 30, randomEq(10)));
        write(randomTest(50, 50, randomEq(10)));
        write(getLargeNumberOfTasks(100, 200, randomEq(100)));
        write(getLargeNumberOfTasks(MAXN2, MAXT2, randomEq(100)));
        write(getLargeNumberOfTasks(MAXN2, MAXT, randomEqInt(MAXCOST2 / 2, MAXCOST2)));
        write(getFewDifferentTimes(MAXN2, 10 * MAXN2, randomEq(MAXCOST2)));
        write(getFewDifferentTimes(MAXN2, MAXT, randomEq(MAXCOST2)));
        for (int i = 0; i < 3; i++) {
            write(randomTest(900 + rand.nextInt(100), MAXT, new EqualsCostProducer(rand.nextInt(MAXCOST2) + 1)));
        }
        write(randomTest(MAXN2, MAXT, new EqualsCostProducer(rand.nextInt(MAXCOST2) + 1)));
        write(randomTest(MAXN2, MAXT, randomEqInt(MAXCOST2 / 2, MAXCOST2)));
        // N>1000, C=const, 10 tests
        write(randomTest(MAXN, MAXT2, new EqualsCostProducer(rand.nextInt(MAXCOST) + 1)));
        write(getFewDifferentTimes(MAXN, 10 * MAXN2, randomEqInt(MAXCOST2 / 2, MAXCOST2)));
        write(getFewDifferentTimes(MAXN, MAXT, randomEqInt(MAXCOST2 / 2, MAXCOST2)));
        write(getLargeNumberOfTasks(MAXN, MAXT2, randomEq(100)));
        write(getLargeNumberOfTasks(MAXN, MAXT, randomEqInt(MAXCOST2 / 2, MAXCOST2)));
        for (int i = 0; i < 3; i++) {
            write(randomTest(90000 + rand.nextInt(10000), MAXT, new EqualsCostProducer(rand.nextInt(MAXCOST2) + 1)));
        }
        write(randomTest(MAXN, MAXT, new EqualsCostProducer(rand.nextInt(MAXCOST) + 1)));
        write(randomTest(MAXN, MAXT, randomEqInt(MAXCOST / 2, MAXCOST)));
        // N<=1000, 10 tests
        write(randomTest(10, 10, new RandomCostProducer(10)));
        write(randomTest(15, 15, new RandomCostProducer(MAXCOST2)));
        write(randomTest(50, 50, new RandomCostProducer(50)));
        write(randomTest(100, 100, new RandomCostProducer(100)));
        write(getFewDifferentTimes(MAXN2, MAXT, new RandomCostProducer(MAXCOST2)));

        write(getLargeNumberOfTasks(MAXN2, MAXT2, new RandomCostProducer(100)));
        write(randomTest(900 + rand.nextInt(100), MAXT, new RandomCostProducer(MAXCOST2)));
        write(randomTest(900 + rand.nextInt(100), MAXT, new RandomCostProducer(MAXCOST2)));
        write(randomTest(MAXN2, MAXT, new RandomCostProducer(1000)));
        write(randomTest(MAXN2, MAXT, new RandomCostProducer(MAXCOST2)));

        //Other, 15 tests


        write(randomTest(MAXN, 100, new RandomCostProducer(MAXCOST2)));
        write(getFewDifferentTimes(90000 + rand.nextInt(10000), 100, new IntervalCostProducer(MAXCOST / 2, MAXCOST)));
        write(getLargeNumberOfTasks(MAXN, MAXT, new RandomCostProducer(MAXCOST2)));
        write(getLargeNumberOfTasks(MAXN, MAXT, new IntervalCostProducer(MAXCOST / 2, MAXCOST)));
        write(getFewDifferentTimes(90000 + rand.nextInt(10000), 10 * MAXN, new IntervalCostProducer(MAXCOST / 2, MAXCOST)));

        write(getFewDifferentTimes(MAXN, MAXT, new IntervalCostProducer(MAXCOST / 2, MAXCOST)));
        for (int i = 0; i < 3; i++) {
            write(getLargeNumberOfTasks(90000 + rand.nextInt(10000), MAXT, new RandomCostProducer(MAXCOST2)));
        }
        for (int i = 0; i < 4; i++) {
            write(randomTest(90000 + rand.nextInt(10000), MAXT, new RandomCostProducer(MAXCOST)));
        }
        write(randomTest(MAXN, MAXT, new RandomCostProducer(MAXCOST)));
        write(randomTest(MAXN, MAXT, new IntervalCostProducer(MAXCOST / 2, MAXCOST)));

    }

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