Для начала отдельное упражнение – как из индекса буквы в исходной строке получить индекс строки, в которую его положить.
Обозначу число строк переменной
rows
. Период этой «пилы» от верхнего пика до следующего верхнего пика составляет
2 * (rows - 1)
. Остаток от деления на этот период будет означать позицию внутри одного «зуба»:
остаток: 0 1 2 3 4 5
строка: 0 1 2 3 2 1 – это хочется в итоге как-то получать
Чтобы просчитать «отражение» – когда шли вниз и потом стали идти вверх – надо подогнать этот момент и сделать пересечением оси
y = 0
и тогда отражение легко сделать, взяв абсолютное значение
Math.abs()
:
y : 3 2 1 0 -1 -2
abs: 3 2 1 0 1 2
Остаток от деления будет всегда положительным и растущим:
0 1 2 3 4 5
, а нужно получить из него
3 2 1 0 -1 -2
. Умножить на -1 и добавить 3:
Math.abs(rows - 1 - ost)
Итого примерно такой код даст правильные номера строк, куда вставлять символ, получая на вход i – индекс буквы в исходной строке:
var i, ost, row, rows=4, period = 2 * (rows - 1); // 0 0 0 | 6 0 0
for(i = 0; i < 10; i++) { // 1 1 1 | 7 1 1
ost = i % period; // 2 2 2 | 8 2 2
row = rows - 1 - Math.abs(rows - 1 - ost); // 3 3 3 | 9 3 3
console.log( i, ost, row); // 4 4 2 | 10 4 2
} // 5 5 1 | 11 5 1
В сборе будет выглядеть примерно так:
function encrypt( text, n) {
var i, ost, period = 2 * (n-1), r, row, out = [];
text = text.replace(/\s/g,""); // убрать пробелы
for(r = 0; r < period; r++) out[r] = ""; // пустые строки
for(i = 0; i<text.length; i++) {
ost = i % period;
row = n - 1 - Math.abs(n - 1 - ost)
out[row] += text.substr(i,1);
}
return out.join("");
}
function test( text, rows) {
var pre = document.createElement("pre");
pre.innerHTML = encrypt(text, rows);
document.body.appendChild(pre);
}
test("этот текст зашифрован", 4); // экинтесшфаоттарвтзо
jsFiddleUpd. чуть переписал это дело. Шифровка и расшифровка осуществляются на основе одной и той же «карты», которая зависит только от числа букв в тексте и числа строк. Поэтому сделал одну ф-ю, создающую эту карту. И слегка отличающиеся короткие функции шифровки и дешифровки.
Фиддл с формой. Код шифровки/дешифровки такой:
function makeMap( len, n) {
var i, pip, period = 2 * ( n - 1);
var rows = Array.apply( null, Array( n)).map( function(){ return []});
for( i = 0; i < len; i++) {
pip = i % period;
r = pip < ( n - 1) ? pip : period - pip;
rows[ r].push( i);
}
return Array.concat.apply( null, rows);
}
function decrypt( text, n) {
var map = makeMap( text.length, n);
return text.split('').reduce(function(p,c,i,a){ return p + a[map.indexOf(i)]},'');
}
function encrypt( text, n) {
var map = makeMap( text.length, n);
return text.split('').reduce(function(p,c,i,a){ return p + a[map[i]]},'');
}