Введение

Однажды я смотрел флешку со своей девушкой Майрой, и в эпизоде ​​Барри Аллен застрял в камере рядом с другим заключенным. Этот другой человек продолжал стучать по стене, и Флэшу не потребовалось много времени, чтобы понять, что он использует код постукивания 5x5.

Майра решила, что было бы «мило» писать письма самим себе в коде, и как гордый разработчик я быстро понял, что могу просто написать модуль, который сделает это за меня, даже если она этого не заметит.

Код

Так что я быстро изучил сам код, который на самом деле не нужен для алгоритма, но мне нравится исследовать случайные вещи. Согласно старой и верной Википедии, заключенные обычно используют «Tap Code» или «Knock Code».

Код касания основан на квадрате Полибия, в котором используется сетка из букв 5 × 5, представляющая все буквы латинского алфавита, кроме K, которая представлена ​​буквой C.

В коде есть два правила:

  • Первый стук обозначает ряд.
  • Второй стук обозначает колонку.

Вот и все, что нам нужно было знать, чтобы реализовать это.

Если вы хотите увидеть код, его можно найти на моей странице github или странице npm.

Настраивать

Есть только одна вещь, которая нужна модулю с точки зрения настройки, и это сама сетка, обратите внимание, что есть способ сделать это без ссылки на сетку с помощью арифметики модуля, но это делает код менее читаемым, поэтому я решил не используй это.

const grid = [ 
  ['A', 'B', 'C', 'D', 'E'],
  ['F', 'G', 'H', 'I', 'J'],
  ['L', 'M', 'N', 'O', 'P'],
  ['Q', 'R', 'S', 'T', 'U'],
  ['V', 'W', 'X', 'Y', 'Z']
];

Не забывайте, что «К» не существует, оно представлено «С».

расшифровать

Метод расшифровки немного проще, так что начните с него.

exports.decrypt = function() { 
  // 1 
  const cypher = arguments[0];
  const decyphered = []; 
  // 2 
  if (typeof cypher !== "string" || cypher.length === 0 || cypher.length % 2 !== 0) {
    throw new Error(`The provided cypher: ${cypher} is not valid`);   
  }
  
  // 3
  for (let i = 0, l = cypher.length; i < l; i += 2) {
    const row = parseInt(cypher.charAt(i), 10) - 1;
    const col = parseInt(cypher.charAt(i + 1), 10) - 1; 
    
    decyphered.push(grid[row][col]);
  }
  // 4
  return decyphered.join("");
};

Эту функцию можно разбить на 4 части:

  1. Сначала необходимо сохранить шифр и создать переменную-заполнитель для хранения расшифрованного значения.
  2. Второй раздел проверяет, чтобы убедиться, что шифр действителен. Это должна быть строка (если она отправлена ​​в виде числа, вы можете получить переполнение переменной), должна иметь длину больше 0 и должна быть четной, поскольку каждую букву представляют 2 стука.
  3. Третий раздел перебирает каждую вторую букву зашифрованного текста и сопоставляет его с сеткой, добавляя возвращенную букву сетки к расшифрованному массиву.
  4. Наконец, четвертая часть просто возвращает расшифрованный текст в виде строки чисел.

Шифровать

Функция шифрования немного более запутанная, но ненамного.

exports.encrypt = function() {
  // 1
  const text = arguments[0];
  const cypher = [];
  
  // 2
  if (typeof text !== "string") {
    throw new Error(`The provided cypher: '${cypher}' is not valid.`);
  } else if (text.length === 0) {
    return "";
  }
  
  // 3
  text = text.toUpperCase();
  text = text.replace(/\s+/g, "");
  text = text.replace(/k/gi, "C");
  // 4
  text.split("").forEach(function(t) {
    for (let i = 0, li = grid.length; i < li; i++) {
      for (let j = 0, lj = grid[i].length; j < lj; j++) {
        if (t === grid[i][j]) {
          cypher.push((i + 1) + "" + (j + 1));
          break;
        }
      }
    }
  });
  // 5
  return cypher.join("");
};

Функция шифрования разделена на 5 частей:

  1. Сначала устанавливаются заполнитель текста и шифра.
  2. Текст должен быть проверен так же, как и для расшифровки, за исключением того, что единственное требование состоит в том, что это непустая строка. Если строка пуста, просто верните ее, нет смысла делать что-либо еще.
  3. В третьей части мы очищаем строку.
  • Сделайте весь текст в верхнем регистре, так как наша сетка сохраняется в верхнем регистре.
  • Удалите все пробелы, так как для пробелов нет сопоставления.
  • Наконец, замените все буквы K на C, поскольку для K нет сопоставления.
  1. Наконец, мы перебираем все символы в текстовой строке и кодируем ее. Для этого мы перебираем все строки сетки и сохраняем расположение строк и столбцов в массиве шифров.
  2. Наконец, мы возвращаем шифрованную строку.

Вывод

Код пять на пять кранов не является сложным алгоритмом для построения. Это один из многих способов сделать это. Это не самый простой и не самый эффективный, но это лучший из тех, что я нашел, чтобы по-настоящему понять, что происходит в шифре.

Если вы запустите шифр, вы должны получить что-то вроде этого:

const five = require("ln-five-five-tap");
five.encrypt("Hello World");
// 23153131345234423114
five.decrypt("23153131345234423114");
// HELLOWORLD

Первоначально опубликовано на marceloluz.com.