Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Шифрование по квадрату Полибия (https://javascript.ru/forum/misc/28236-shifrovanie-po-kvadratu-polibiya.html)

bes 11.05.2012 23:42

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

Корректно работает только для квадратных матриц, что, как я понял, обусловлено самим способом формирования шифра (в википедии он идёт как метод под номером 2), так как идёт перенос строки y-координат в конец строки x-координат и поэтому часть y-координат становятся х-координатами, что и даёт сбои при не квадратных матрицах.

Также для корректности работы приходится добавлять несколько лишних символов к алфавиту.
В моём примере вводимый текст может содержать только русские буквы, пробел, точку и запятую.
charAt() не использовал, хотя наверное можно было.


<body onload = "createTable()">

<style>
table, td {border: solid 1px; text-align: center; float: left}
textarea {wrap: virtual}
</style>

<table id="etable">
</table>

<div id="myDiv">
<textarea id="text"></textarea>
  <input type="button" value="Encode" onclick="encode(text, etext)"><br>
<textarea id="etext"></textarea>
  <input type="button" value="Decode" onclick="decode(etext, dtext)"><br>
<textarea id="dtext"></textarea>
</div>


<script>
//алфавит также включает точку, запятую и пробел
var alphabet = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ., ";
//параметры таблицы
var rows = 6;
var cols = 6;

//выводит таблицу
function createTable() {
var k = 0; 
  for (var i = 0; i < rows; i++) {
    tr = document.createElement('tr');
      etable.appendChild(tr);
  
    for (var j  = 0; j < cols; j++) {
       td = document.createElement('td');
       td.innerHTML = alphabet[j+k];
       tr.appendChild(td);
      }
      k = k + cols;
  }
}


//второй вариант вывода таблицы
function createTable2() {
var k = 0; 
var str = "";

  for (var i = 0; i < rows; i++) {
    str = str +'<tr>';

    for (var j = 0; j < cols; j++) {
      str = str + '<td>' + alphabet[j+k];
    }
    str = str + '</tr>'
    k = k + cols;
  }

etable.innerHTML = str;
}


//координаты символа
function pos(symbol) {
var  k = alphabet.indexOf(symbol);
var x = k % cols; 
var  y = parseInt(k/cols); 
var xy = [];
  xy[0] = x;
  xy[1] = y;
return xy; 
}


//символ по координатам
function symbol(x, y) {
var n = parseInt(y) * cols + parseInt(x);
  return alphabet[n]; 
}


//шифрует
function encode(source, target) {
var str = source.value.toUpperCase(); //регистронезависимость текста
var allX = "";
var allY = "";
var estr = "";
var mas = [];
var l = str.length;

  for (var i  = 0; i < l; i++) {
    mas = pos(str[i]); 
    allX = allX + mas[0]; 
    allY = allY + mas[1];
  }

var all = allX + allY; 
var k = all.length;

  for (var i = 0; i < k; i = i + 2) {
    estr = estr + symbol( all[i], all[i+1] ); 
  }   

target.value = estr;
}


//дешифрует
function decode(source, target) {
var str = source.value.toUpperCase(); 
var all = "";
var dstr = "";
var mas = [];
var l = str.length;

  for (var i = 0; i < l; i++) {
    mas = pos(str[i]); 
    all = all + mas[0] + mas[1] ;
  }

var k = all.length/2;
var allX = all.slice (0, k); 
var allY = all.slice(k); 

  for (var i = 0; i < k; i++) {
    dstr = dstr + symbol(allX[i], allY[i] ); 
  }

target.value = dstr;
}
</script>

bes 12.05.2012 12:29

Странно, неужели ни к чему нельзя придраться??

B@rmaley.e><e 12.05.2012 12:38

У Вас создаётся куча глобальных переменных.

bes 12.05.2012 13:19

Цитата:

Сообщение от B@rmaley.e><e
У Вас создаётся куча глобальных переменных.

Просьба пояснить, где именно.

zebra 12.05.2012 14:06

Везде где объявление переменной без var

bes 12.05.2012 14:18

Цитата:

Сообщение от zebra
Везде где объявление переменной без var

Такие переменные только в циклах, но почему их создаётся куча?

nerv_ 12.05.2012 14:43

Цитата:

Сообщение от bes
но почему их создаётся куча?

потому, что они объявляются без инструкции var

dmitriymar 12.05.2012 14:53

Цитата:

Сообщение от bes
for (i=0; i<str.length; i++) {

да и подобные конструкции
str.length -вычисляется при каждой итерации

bes 12.05.2012 15:11

Цитата:

Сообщение от dmitriymar
str.length

Да, надо вынести из условия.

Цитата:

Сообщение от nerv_
потому, что они объявляются без инструкции var

Правильно ли я понимаю, что если в цикле внутри функции счётчик i не объявлен в выражении var i, то создаётся одна глобальная переменная i,
после выполнения функции, эта глобальная переменная висит в памяти, когда функция запускается вновь она использует уже созданную переменную i.

nerv_ 12.05.2012 15:42

Цитата:

Сообщение от bes
Правильно ли я понимаю

что мешает самому проверить? :)

Цитата:

Сообщение от bes
035 td = document.createElement('td');
036 td.innerHTML = alphabet[j+k];
037 tr.appendChild(td);

лучше создавать таблицу целиком (строкой) и затем ее парсить (innerHTML)

bes 12.05.2012 16:09

Цитата:

Сообщение от nerv_
что мешает самому проверить?

Да как-то сразу и не сообразил, что это можно проверить, хотелось узнать от опытных людей как лучше использовать циклы c var i или просто с i.

Если так как я подумал, то все циклы всех запускаемых функций, в которых используется счётчик i, будут использовать эту переменную.
Поэтому наверное имеет смысл объявить i как глобальную (или совсем её не объявлять, раз уж всё равно сама создаётся), а в условиях циклов не использовать выражение var i (и не использовать i для других целей, так как её значение будет зависеть от последнего исполненного цикла).
Попробую проверить.


Цитата:

Сообщение от nerv_
лучше создавать таблицу целиком (строкой) и затем ее парсить (innerHTML)

Попробую, чем лучше-то, то что без createElement и appendChild

bes 12.05.2012 16:32

nerv_, посмотрите функцию createTable2(), это вы имели в виду?

nerv_ 12.05.2012 16:52

Цитата:

Сообщение от bes
nerv_, посмотрите функцию createTable2(), это вы имели в виду?

почти. Зачем конкатенацию так часто производить?
Array.push()
Array.join()
Цитата:

Сообщение от bes
Если так как я подумал, то все циклы всех запускаемых функций, в которых используется счётчик i, будут использовать эту переменную.
Поэтому наверное имеет смысл объявить i как глобальную (или совсем её не объявлять, раз уж всё равно сама создаётся), а в условиях циклов не использовать выражение var i (и не использовать i для других целей, так как её значение будет зависеть от последнего исполненного цикла).
Попробую проверить.

Глобальные переменные надо создавать только тогда, когда это действительно необходимо.

bes 12.05.2012 17:11

Цитата:

Сообщение от nerv_
Глобальные переменные надо создавать только тогда, когда это действительно необходимо.

То есть в циклах всегда желательно использовать var i ?

nerv_ 12.05.2012 17:35

Мое мнение заключается в том, что переменные надо объявлять всегда. Предпочитаю делать это в начале функции.
Кстати, однобуквенные переменные не есть гуд. Имена переменных должны говорить сами за себя

bes 12.05.2012 18:24

Цитата:

Сообщение от nerv_
Мое мнение заключается в том, что переменные надо объявлять всегда. Предпочитаю делать это в начале функции.

Я предпочитаю объявлять переменные ближе к смысловым блокам, в которых они используются, если используются во многих блоках, то также вначале.

Цитата:

Сообщение от nerv_
Кстати, однобуквенные переменные не есть гуд. Имена переменных должны говорить сами за себя

Не спорю, что-то желательно назвать со смыслом, а где-то проще понять фразу если использовать короткое имя (которое, кстати, при желании можно закомментировать).
Как, например, назвать переменную k в функции createTable (увеличительНаКоличествоС олбцов что ли, не очень-то понятное выражение получится из таких имён).


Проверка показала, что я правильно думал, то есть во всех циклах используется одна и та же переменная i, то есть B@rmaley.e><e был неправ, что в коде создаётся много глобальных переменных.
Тут вопрос спорный получается использовать или не использовать var i в циклах: для порядка, конечно, чтобы не висела эта i в памяти, надо использовать var i, а в принципе, если уверен, что нигде эту i больше использовать не будешь, можно и без var.


nerv_, не очень понял что нужно сделать в вашем способе, используя push() и join(): перевести строку в массив что ли, а потом каким-то образом вклинить туда <tr><td> и </tr><td>.

B@rmaley.e><e 12.05.2012 18:55

Цитата:

Сообщение от bes
B@rmaley.e><e был неправ, что в коде создаётся много глобальных переменных

tr, i, j, td в довесок к уже существующим — этого мало?
Их вообще ни одной не должно быть.

bes 12.05.2012 19:09

Цитата:

Сообщение от B@rmaley.e><e
tr, i, j, td в довесок к уже существующим — этого мало?

Теперь понятно сколько для вас много.

Цитата:

Сообщение от B@rmaley.e><e
Их вообще ни одной не должно быть.

Как тогда решать, например, с такими как alphabet, rows, cols, которые используются во многих функциях??

nerv_ 12.05.2012 19:11

Цитата:

Сообщение от bes
B@rmaley.e><e был неправ

На моей памяти такого не было :)
Цитата:

Сообщение от bes
Как, например, назвать переменную k в функции createTable (увеличительНаКоличествоС олбцов что ли, не очень-то понятное выражение получится из таких имён).

Это твоя проблема, что ты не можешь придумать хорошие имена. Не вникая в суть - stepСolumn
Цитата:

Сообщение от B@rmaley.e><e
nerv_, не очень понял что нужно сделать в вашем способе, используя push() и join(): перевести строку в массив что ли, а потом каким-то образом вклинить туда <tr><td> и </tr><td>.

snake - первая функция в листинге. Я не утверждаю, что являюсь образцовым кодером, но на этот счет, как мне кажется, прав.

B@rmaley.e><e 12.05.2012 20:18

Цитата:

Сообщение от bes
Как тогда решать, например, с такими как alphabet, rows, cols, которые используются во многих функциях??

Замыкания.

bes 12.05.2012 21:11

Цитата:

Сообщение от nerv_
Это твоя проблема, что ты не можешь придумать хорошие имена. Не вникая в суть - stepСolumn

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

Цитата:

Сообщение от nerv_
snake - первая функция в листинге

В твоём примере используется один push в цикле, в моём придётся использовать три, то есть 3 push() vs 2 concat(), если concat намного более затратная операция по сравнению с push, тогда, конечно смысл есть, а если нет, то у меня получилось не сложнее (за сам способ спасибо).

Цитата:

Сообщение от B@rmaley.e><e
Замыкания.

Можете пояснить, не совсем понятно как замыкания могут заменить глобальные переменные.

B@rmaley.e><e 12.05.2012 21:27

(function(){
  var localVariable = 5;

  window.getLocalVar = function () { return localVariable; };
  window.setLocalVar = function (val) { localVariable = val; };
})();

alert( typeof localVariable);
alert( getLocalVar() );
setLocalVar(10);
alert( getLocalVar() );

nerv_ 12.05.2012 22:11

из этого кода следует, что ты прав ;) Прикольное кино :) Даже если явно задать длину массива new Array(count) и при записи обращаться непосредственно к каждому элементу Array[index] ситуация почти аналогична. Вру )
var repeatCount = 100000;
var pattern = "text";
var arrayFixSize = new Array( repeatCount );
var startTime;
var counter;
var line = "";
var arr = [];


for( startTime = new Date(), counter = repeatCount; counter > 0; counter-- ) {
	line += pattern;
}

alert(
	'concatenate - ' + ( new Date() - startTime )
);

/*********************************************************/

for( startTime = new Date(), counter = repeatCount; counter > 0; counter-- ) {
	arr.push( pattern );
}

arr.join( '' );
alert(
	'array + push - ' + ( new Date() - startTime )
);

/*********************************************************/

for( startTime = new Date(), counter = repeatCount; counter > 0; counter-- ) {
	arrayFixSize[ counter ] = pattern;
}

arrayFixSize.join( '' );
alert(
	'array[ index ] - ' + ( new Date() - startTime )
);


Итог: во всех браузерах разное время, с точностью до наоборот :)

StelZ 12.05.2012 22:15

bes, не пойму по какому принципу работает данная программа. она же должна присваивать букве определенное число, равное номеру ряда и столбца (первый ряд(1) и первый столбец(1) - буква а - 11), и выводить переведенный текст в другое окошко

bes 12.05.2012 22:28

Получается что к глобальным переменным придётся обращаться не напрямую, а через get/set методы, наподобие того как в Delphi обращаются к полям через свойства, только без сохранения синтаксиса обращения.
И всё это, как я понимаю, из-за того что не обеспечена модульность (весь скрипт по каким бы он файлам не был разбросан воспринимается как единый модуль).

bes 12.05.2012 22:35

Цитата:

Сообщение от StelZ
bes, не пойму по какому принципу работает данная программа. она же должна присваивать букве определенное число, равное номеру ряда и столбца (первый ряд(1) и первый столбец(1) - буква а - 11), и выводить переведенный текст в другое окошко

Можно, конечно, и так сделать, то есть считать конечным шифром числа.
Я взял за основу описанный в википедии метод 2, когда получают координаты, затем к строке x-координат приписывают строку y-координат, а затем последовательно берут пары из строки, считают их координатами и переводят в буквы по той же таблице, то есть конечный шифр - слова.

B@rmaley.e><e 12.05.2012 22:48

Цитата:

Сообщение от bes
Получается что к глобальным переменным придётся обращаться не напрямую, а через get/set методы, наподобие того как в Delphi обращаются к полям через свойства, только без сохранения синтаксиса обращения.

Нет, неправильно получается. get и set функции приведены для примера, вместо них можно было реализовать любые другие функции, работающие с нужной переменной.

bes 12.05.2012 22:56

Цитата:

Сообщение от B@rmaley.e><e
Нет, неправильно получается. get и set функции приведены для примера, вместо них можно было реализовать любые другие функции, работающие с нужной переменной.

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

B@rmaley.e><e 12.05.2012 23:18

А Вам нигде из клиентского кода не нужно ею пользоваться.

bes 12.05.2012 23:24

nerv_, IE8 вообще подвисает на этом скрипте (потом отвисает выдавая результаты).
Хотя concat чаще выигрывает, изредка push немного опережает.

Цитата:

Сообщение от B@rmaley.e><e
А Вам нигде из клиентского кода не нужно ею пользоваться.

В смысле??

nerv_ 12.05.2012 23:58

B@rmaley.e><e, разрешите вопрос по приведенному мною коду: как правильней делать и есть ли среди данных вариантов "тот самый"? Т.е. как правильно (если можно так выразиться) в javascript выполнять конкатенацию? В vba могу сказать точно, этот способ line += pattern; самый медленный. Противоречивые результаты тестов в различных браузерах не позволяют прийти к единственно верному выводу. Или смысл в том, что заморачиваться не стоит line += pattern; да и фиг с ним?
bes, ты еще в хроме проверь )

bes 13.05.2012 00:06

Цитата:

Сообщение от nerv_
bes, ты еще в хроме проверь )

С него и начинаю, здесь главное не цифры, главное соотношение.

B@rmaley.e><e 13.05.2012 01:50

Цитата:

Сообщение от nerv_
Или смысл в том, что заморачиваться не стоит line += pattern; да и фиг с ним?

Именно. Вряд ли Вы когда-нибудь столкнётесь с тормозами конкатенации.
Цитата:

Сообщение от bes
В смысле?

В смысле, Ваши глобальные переменные нужны только Вашему коду и никакому другому.

person 13.05.2012 05:26

Здесь рассказывается чем отличается переменная с var и без.

Тонкости ECMA-262-3. Часть 2. Объект переменных.

Цитата:

Часто, в различных статьях о JavaScript, можно видеть утверждения вроде: “глобальные переменные можно объявлять и с var (в глобальном контексте) и без var (в любом месте)”. Это не так. Запомните:

переменные объявляются только с ключевым словом var.

Присвоение же вроде:

a = 10;лишь создаёт очередное свойство (но не переменную) в глобальном объекте. “Не переменную” не в том смысле, что её нельзя изменить, а “не переменную” в понятии переменных в ECMAScript (которые затем также станут свойствами глобально объекта посредством VO(globalContext) === global, помним, да?).

А разница следующая (покажем на примере):

alert(a); // undefined
alert(b); // "b" is not defined

b = 10;
var a = 20;Всё, опять же, вытекает из VO и стадий его модификации (вход в контекст, исполнение контекста):
by Dmitry A. Soshnikov

nerv_ 13.05.2012 11:24

B@rmaley.e><e, спасибо :)


Часовой пояс GMT +3, время: 09:02.