
/**
 * Zig-zag Cipher
 * Problem 2, AIC 2004 (Senior)
 * Java Sample Solution
 */

/**
 * This solution deciphers the message by:
 *  - first determining the length of the original message, textLength;
 *  - encrypting the integers 0 .. textLength-1 according to the scheme in the
 *    question.
 *  - reading the numbers left-to-right, top-to-bottom from the step above to
 *    generate a table that links index in the encrypted text to an index in
 *    the plain text.
 *  - use this table to decrypt the message.
 *
 * For example, to decrypt COPATGAHRRY in 3 rows, we consider the 11 integers
 * 0, 1, 2, ... 11. Encrypting this into a 2-D array, dummyText, makes the
 * array look like:
 *
 *   0 5 6 11
 *   1 4 7 10
 *   2 3 8 9
 *
 * We can then generate a table, decryptMap, that matches the position in the
 * encrypted text to their index in the original text:
 *
 *            i  0    1    2    3    4    5    6    7    8    9   10   11
 * decryptMap[i] 0    5    6   11    1    4    7   10    2    3    8    9
 *
 * We can then read the original message by printing out the characters in the
 * order given by the table.
 *
 */

import java.io.*;

class Solution {
    public static final int MAXMESSAGE = 10000;
    public static final int MAXROWS = 100;

    // Input and output files
    private static BufferedReader in;
    private static BufferedWriter out;

    // decryptMap[i] = ciphertext index for plaintext[i].
    private static int[] decryptMap = new int[MAXMESSAGE];

    private static int[][] dummyText = new int[MAXROWS][MAXMESSAGE];
    private static int[] rowLen = new int[MAXROWS];

    private static int rows;
    private static String ciphertext;

    /**
     * Read the next token from the input file.
     * Tokens are separated by whitespace, i.e., spaces, tabs and newlines.
     * If end-of-file is reached then an empty string is returned.
     */
    private static String readToken() throws IOException {
        StringBuffer ans = new StringBuffer();
        int next;

        // Skip any initial whitespace.
        next = in.read();
        while (next >= 0 && Character.isWhitespace((char)next))
            next = in.read();

        // Read the following token.
        while (next >= 0 && ! Character.isWhitespace((char)next)) {
            ans.append((char)next);
            next = in.read();
        }

        return ans.toString();
    }

    /**
     * The main program.
     */
    public static void main(String[] args) throws IOException {
        // Open the I/O files.
        in = new BufferedReader(new FileReader("zigin.txt"));
        out = new BufferedWriter(new FileWriter("zigout.txt"));

        // Read the number of rows the deciphered text will fill.
        rows = Integer.parseInt(readToken());

        // Clear the rowLen array - assume all rows are empty.
        for (int i = 0; i < rows; i++)
            rowLen[i] = 0;

        // Read in the first line of text.
        StringBuffer ciphertextBuffer = new StringBuffer();
        String text;
        text = readToken();
        // If the current line of text is a "#", then we have the entire input.
        while (!text.equals("#")) {
            // We have a string which is not just a #
            // Append it to the existing string.
            ciphertextBuffer.append(text);

            // Read in the next line.
            text = readToken();
        }
        ciphertext = ciphertextBuffer.toString();
	in.close();

        // We know the length of the encrypted text and the number of rows that it
        // fills.
        //
        // Fill in the dummyText array with the encrypted version of the integers
        // 0 .. textLength-1.
        int currRow = 0; // Starting at row 0.
        int currDir = 1; // Heading down to begin with.
        for (int i = 0; i < ciphertext.length(); i++) {
            // Mark this position in the dummy array.
            dummyText[currRow][rowLen[currRow]] = i;
            rowLen[currRow]++;

            // Move to the next row for the next character.
            currRow += currDir;

            // If we are at the top or the bottom, change direction.
            if (currRow == rows - 1)
                currDir = -1;
            else if (currRow == 0)
                currDir = 1;
        }

        // Construct the decryptMap array from the dummyText.
        int pos = 0;
        for (currRow = 0; currRow < rows; currRow++)
            for (int i = 0; i < rowLen[currRow]; i++)
                decryptMap[dummyText[currRow][i]] = pos++;

        // We now know the order to print out the letters from the plain text.
        for (pos = 0; pos < ciphertext.length(); pos++)
            out.write(ciphertext.charAt(decryptMap[pos]));
        out.newLine();
        out.close();
    }
}

