kostyaostapuk
@kostyaostapuk

Как зашифровать строку методом «Железнодорожной изгороди»?

str="этоттекстзашифрован";

<pre>
      э        к         и         н
       т     е   с     ш   ф     а
        о   т     т   а     р   в
          т         з         о
    </pre>
  • Вопрос задан
  • 5255 просмотров
Решения вопроса 1
sergiks
@sergiks Куратор тега JavaScript
♬♬
Для начала отдельное упражнение – как из индекса буквы в исходной строке получить индекс строки, в которую его положить.

Обозначу число строк переменной 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); // экинтесшфаоттарвтзо

jsFiddle

Upd. чуть переписал это дело. Шифровка и расшифровка осуществляются на основе одной и той же «карты», которая зависит только от числа букв в тексте и числа строк. Поэтому сделал одну ф-ю, создающую эту карту. И слегка отличающиеся короткие функции шифровки и дешифровки. Фиддл с формой. Код шифровки/дешифровки такой:
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]]},'');
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы