More efficient columnar transposition decryption Below, I have created a rudimentary script to decipher a columnar transposition. I am wondering if there is a more efficient way to determine the number of the rows in a column? Also, is there a way to build the resulting string without creating a matrix in the interim?

Overview

Quick refresher for columnar transpositions.

Method 1

Given a key of 3,

the text 'Attack at dawn' is transposed into three columns...

1   2   3
A   t   t
a   c   k
a   t   D
a   w   n


...joining each column; left->right, top->bottom; will result in the following text:

Aaaa tctw tkDn


Method 2

Given a key 'table',

the text 'Attack at dawn' is transposed into five columns (length of the key)...

t   a   b   l   e
A   t   t   a   c
k   a   t   D   a
w   n


...joining the columns, as described above, result in the following text:

tAkw atan btt laD eca


Code

Is there a better way to determine how many rows will be present for each column?

function decrypt(ciphertext, key) {
    var chars   = normalizeText(ciphertext);
    var len     = chars.length;
    var isStr   = typeof key === 'string';
    var cols    = isStr ? key.length : key;
    var rows    = Math.ceil(len / cols);
    var mod     = divMod(len, cols)[1];
    var matrix  = Matrix(rows, cols, '');
    var counter = 0;
    for (var col = 0; col &lt; cols; col++) {
        var remainder = mod !== 0 &amp;&amp; col &gt;= mod ? 1 : 0;
        for (var row = 0; row &lt; rows - remainder; row++) {
            matrix[row][col] = chars[counter++];
        }
    }
    return (function(plaintext, startIndex) {
        return plaintext.substr(startIndex);
    }(matrix.reduce(function(result, row) {
        return result + row.join('');
    }, ''), isStr ? cols : 0));
}


Demo



[ [ 'Aaaa tctw tkDn'       , 3       ],
  [ 'tAkw atan btt laD eca', 'table' ]
].forEach(function(cipher) {
    println(decrypt(cipher[0], cipher[1]));
});

function decrypt(ciphertext, key) {
    var chars   = normalizeText(ciphertext);
    var len     = chars.length;
    var isStr   = typeof key === 'string';
    var cols    = isStr ? key.length : key;
    var rows    = Math.ceil(len / cols);
    var mod     = divMod(len, cols)[1];
    var matrix  = Matrix(rows, cols, '');
    var counter = 0;
    for (var col = 0; col &lt; cols; col++) {
        var remainder = mod !== 0 &amp;&amp; col &gt;= mod ? 1 : 0;
        for (var row = 0; row &lt; rows - remainder; row++) {
            matrix[row][col] = chars[counter++];
        }
    }
    return (function(plaintext, startIndex) {
        return plaintext.substr(startIndex);
    }(matrix.reduce(function(result, row) {
        return result + row.join('');
    }, ''), isStr ? cols : 0));
}
function divMod(y, x) {
    return [~~(y / x), y % x];
}
function normalizeText(ciphertext) {
    return ciphertext.replace(/ +/g, "").split('');
}
function Matrix(rows, cols, defaultVal) {
    defaultVal = defaultVal !== undefined ? defaultVal : 0;
    var arr = [];
    for (var i = 0; i &lt; rows; i++) {
        arr.push([]);
        arr[i].push(new Array(cols));
        for (var j = 0; j &lt; cols; j++) {
            arr[i][j] = defaultVal;
        }
    }
    return arr;
}
function print(str, targetEl) {
    return (function (el) {
        return el.html(el.html() + (str || ''));
    }(targetEl || $('#out')));
}
function println(str, targetEl) {
    print((str || '') + '&lt;br /&gt;', targetEl)
}
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;div id="out"&gt;&lt;/div&gt;
Allow me to provide a bit of a different approach. I know it does not exactly answer your questions, but I believe it makes them somewhat obsolete.

This is how I would do the decrypt:

function decrypt(sentence) {
    var result = '';
    var pos = 0;

    var words = sentence.split(' ');
    words = words.map(function(word) {
       return word.split(''); 
    });

    while(true) {
       char = words[pos].shift();
        if (! char) {
            break;
        }
        result += char;

        pos = pos &gt; words.length -2 ? 0 : pos + 1;
    }

    return result;
}


For a working example: http://jsfiddle.net/35jyyv8g/1/

Note that I left the key out, since it is not really necessary with the spaces in the input.