import static java.lang.System.exit;

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

public class TestsGen {

    static class Test {
        int maxLength;
        String text;

        public Test(int maxLength, String text) {
            this.maxLength = maxLength;
            this.text = text;
        }
    }

    static final Random rand = new Random(26012012);
    private static final int MINLINKLENGTH = 8;
    final static String LINK_ALPHABET;

    static {
        StringBuilder s = new StringBuilder();
        for (char c = 'a'; c <= 'z'; c++) {
            s.append(c);
        }
        for (char c = '0'; c <= '9'; c++) {
            s.append(c);
        }
        s.append('/').append('.');
        LINK_ALPHABET = s.toString();
    }

    static int currentTest;

    static void printTest(Test test) {
        ++currentTest;
        System.err.print("[" + currentTest + "]");
        try {
            PrintWriter out = new PrintWriter(currentTest / 10 + ""
                    + currentTest % 10);
            out.println(test.maxLength);
            if (currentTest % 5 != 0) {
                while (test.text.contains("  ")) {
                    test.text = test.text.replaceAll("  ", " ");
                }
            }
            out.println(test.text);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
            exit(1);
        }
    }

    public static void main(String[] args) {
        {
            int[] maxLength = new int[]{10, 239, 1000};
            int[] length = new int[]{16, 566, 10000};
            for (int i = 0; i < maxLength.length; i++) {
                printTest(getStartingWithLink(maxLength[i], length[i]));
            }
        }
        {
            int[] maxLength = new int[]{10, 239, 1000};
            int[] length = new int[]{21, 245, 1300};
            for (int i = 0; i < maxLength.length; i++) {
                printTest(getEndingWithLink(maxLength[i], length[i]));
            }
        }
        {
            int[] maxLength = new int[]{13, 1000, 10, 45,
                    890, 1000};
            int[] length = new int[]{17, 2000, 16, 43,
                    2000, 10000};
            for (int i = 0; i < maxLength.length; i++) {
                printTest(getRandom(maxLength[i], length[i]));
            }
        }
        {
            int[] number = {2, 10, 15, 17, 466};
            int[] numberToCompress = {1, 7, 3, 15, 239};
            int[] length = {100, 50, 70, 35, 17};
            for (int i = 0; i < number.length; i++) {
                printTest(getManyLink(number[i], numberToCompress[i], length[i]));
            }
        }
        {
            int[] number = {35, 71, 150};
            int[] length = {110, 50, 60};
            for (int i = 0; i < number.length; i++) {
                printTest(getManyLink2(number[i], length[i]));
            }
        }
    }

    private static Test getStartingWithLink(int maxLength, int length) {
        String s = getTextWithoutLink(length);
        String link = getLinkByParam(maxLength, length - 2);
        int pos = 0;
        return new Test(maxLength, s.substring(0, pos) + link + " "
                + s.substring(pos + link.length() + 1));
    }

    private static Test getEndingWithLink(int maxLength, int length) {
        String s = getTextWithoutLink(length);
        String link = getLinkByParam(maxLength, length - 2);
        int pos = s.length() - link.length() - 1;
        return new Test(maxLength, s.substring(0, pos) + " " + link
                + s.substring(pos + link.length() + 1));
    }

    private static Test getRandom(int maxLength, int length) {
        String s = getTextWithoutLink(length);
        String link = getLinkByParam(maxLength, length - 4);
        int pos;
        pos = random(1, s.length() - link.length() - 3);
        pos = s.substring(0, pos).lastIndexOf(' ');
        if (pos <= 0) {
            pos = 1;
        }
        return new Test(maxLength, s.substring(0, pos) + " " + link + " "
                + s.substring(pos + link.length() + 2));
    }

    static Test getManyLink(int links, int linksToCompress, int maxLength) {
        String s = getTextWithoutLink(rand.nextInt(maxLength));
        int len = s.length();
        for (int i = 0; i < links; i++) {
            String link = getLink(rand.nextInt(maxLength));
            if (i + 1 < linksToCompress) {
                len += 5;
            } else if (i + 1 > linksToCompress) {
                len += 2 + rand.nextInt(link.length());
            } else {
                len += 2 + link.length();
            }
            s += " " + link + " ";
            String textWithoutLink = getTextWithoutLink(rand.nextInt(maxLength) + 1);
            len += textWithoutLink.length();
            s += textWithoutLink;
        }
        return new Test(len, s);
    }

    static Test getManyLink2(int links, int maxLength) {
        String s = getTextWithoutLink(rand.nextInt(maxLength));
        int len = s.length();
        for (int i = 0; i < links; i++) {
            String link = getLink(rand.nextInt(maxLength));
            len += 5;
            s += " " + link + " ";
            String textWithoutLink = getTextWithoutLink(rand.nextInt(maxLength) + 1);
            len += textWithoutLink.length();
            s += textWithoutLink;
        }
        return new Test(rand.nextInt(len), s);
    }

    static String getLinkByParam(int maxLength, int length) {
        int toRemove = (length - maxLength);
        int linkLength = -1;
        boolean ok = rand.nextBoolean();
        if (ok) {
            if (toRemove > 9) {
                linkLength = random(9, toRemove);
            }
            if (toRemove < length) {
                linkLength = random(Math.max(9, toRemove), length);
            }
        } else {
            if (toRemove < length) {
                linkLength = random(Math.max(9, toRemove), length);
            }
            if (toRemove > 9) {
                linkLength = random(9, toRemove);
            }
        }
        if (linkLength < 0) {
            linkLength = random(9, length);
        }
        String link = getLink(linkLength);
        return link;
    }

    static String getTextWithoutLink(int length) {
        StringBuilder sb = new StringBuilder();
        if (rand.nextInt(4) == 0) {
            for (int i = 0; i < length; i++) {
                int character;
                do {
                    character = random(32, 126);
                } while (LINK_ALPHABET.indexOf((char) character) >= 0);
                sb.appendCodePoint(character);
            }
            if (sb.charAt(0) == ' ') {
                sb.setCharAt(0, (char) random(33, 126));
            }
            if (sb.charAt(length - 1) == ' ') {
                sb.setCharAt(length - 1, (char) random(33, 126));
            }
        } else {
            while (sb.length() < length - 11) {
                int pseudoLinkLength = Math.min(length - sb.length() - 2,
                        random(10, 20));
                if (rand.nextBoolean()) {
                    sb.append("http://");
                } else {
                    sb.append("http://");
                    for (int i = 8; i < pseudoLinkLength - 1; i++) {
                        sb.appendCodePoint(random(33, 126));
                    }
                    int character;
                    do {
                        character = random(33, 126);
                    } while (LINK_ALPHABET.indexOf((char) character) >= 0);
                    sb.appendCodePoint(character);
                    sb.append(' ');
                }
                sb.append(' ');
            }
            while (sb.length() < length) {
                sb.appendCodePoint(random(33, 126));
            }
        }
        return sb.toString();
    }

    static int random(int a, int b) {
        return rand.nextInt(b - a + 1) + a;
    }

    static String getLink(int length) {
        if (length < MINLINKLENGTH) {
            length = MINLINKLENGTH;
        }
        StringBuilder sb = new StringBuilder("http://");
        while (sb.length() < length) {
            int letter = rand.nextInt(LINK_ALPHABET.length());
            sb.append(LINK_ALPHABET.charAt(letter));
        }
        return sb.toString();
    }

}
