Я хочу создать шифр Цезаря, который может кодировать / декодировать печатаемые символы Unicode (кластеры графем с одним и несколькими кодовыми точками, смайлики и т. Д.) Из всего Unicode (кроме области частного использования). Желательно использовать список всех печатаемых символов.
ПРИМЕЧАНИЕ. Несмотря на то, что я хочу создать шифр Цезаря, на самом деле речь идет не о шифровании. Речь идет об исследовании свойств юникода.
Я нашла такие вопросы:
Каков диапазон печатаемых символов Юникода?
Шифр со всеми символами Юникода
Но я не получил ответа на то, что хочу.
Примечание: если вы дадите кодовый ответ, меня больше всего интересует решение, в котором используется python3 или perl6, поскольку они являются моими основными языками.
Недавно мне дали задание написать шифр Цезаря, а затем закодировать и декодировать английский текст.
Я решил это в python, используя встроенную константу string.printable библиотеки строк. Вот распечатка константы: (я использовал код Visual Studio)
[см. код Python и результаты ниже]
В документации сказано: '' 'Строка символов ASCII, которые считаются печатаемыми. Это комбинация цифр, букв ascii, знаков препинания и пробелов. '' 'https://docs.python.org/3.6/library/string.html#string-constants
Мне интересно, как вы могли бы создать шифр Цезаря, который мог бы кодировать / декодировать все возможные печатные символы, которые вы можете сделать из кодовых точек Unicode (точно так же, как у вас есть все необходимые шрифты, чтобы увидеть те, которые должны быть видны на экране).
Вот мое понимание того, что значит быть печатным персонажем:
Когда я беру строковую константу python, указанную выше, и перемещаюсь по ней с помощью клавиш со стрелками влево или вправо на клавиатуре, мне требуется ровно 100 штрихов, чтобы добраться до конца (столько же, сколько и количество символов). Похоже, существует взаимно однозначное соответствие между тем, чтобы быть печатным символом и его можно было прочесть одним движением клавиши со стрелкой.
Теперь рассмотрим эту строку:
"????????????????ij क्षि ????"
На основе константы pythons string.printable, эта строка, как мне кажется, состоит из следующих 7 печатных символов: (вы можете найти отдельные кодовые точки по адресу: https://unicode-table.com/en/)
1 (семейство) 2 (латинская малая лигатура Ij) 3 (возврат кариеса) 4 (деванагари кши) 5 (пробел) 6 (непрерывный пробел нулевой ширины) 7 (туз пик)
???????????????? кодовые точки: 128104 8205 128105 8205 128103 8205 128102 (ссылка: https://emojipedia.org/family-man-woman-girl-boy/)
(Строчная латинская лигатура Ij) ij код: 307
Код (возврат каретки): 13
(Деванагари кши) क्षि кодовые точки: 2325 2381 2359 2367
(см. Эту страницу: http://unicode.org/reports/tr29/) (кодовые точки кажутся шестнадцатеричными, а не числовыми)
(Пробел) код: 32
(Пробел нулевой ширины): 65279 (AKA U + FEFF BYTE ORDER MARK (BOM)) (https://en.wikipedia.org/wiki/Byte_order_mark)
(Игральная карта Туз пик) ???? codepoint: 127137
Когда я вставляю эту строку в блокнот и пытаюсь пройти по ней с помощью клавиши со стрелкой, я получаю 10 нажатий клавиш, а не 7, потому что семейным эмодзи нужно 4 нажатия клавиш (вероятно, потому, что блокнот не может справиться с соединителем нулевой ширины, codepoint : 8205, и, конечно же, блокнот не может отображать семейный глиф). С другой стороны, когда я отправляю строку в поиск Google, я могу пройти по всей строке за 7 штрихов.
Затем я попытался создать строку в Perl6, чтобы увидеть, что понимание графемы Perl6 сделает строку:
(Я использую редактор Atom)
[см. код Perl6 и результаты ниже]
perl6 считает, что символ деванагари кши क्षि (4 кодовых точки) на самом деле представляет собой 2 графемы, каждая из которых имеет 2 кодовых точки. Несмотря на то, что он МОЖЕТ быть представлен как два символа, как видно из приведенного выше списка, я думаю, что это ошибка. Предполагается, что Perl6 поддерживает графемы, и даже мой блокнот Windows (и поиск в Google) думает, что это одна графема / символ.
Основываясь на двух строках, практическое определение печатаемого символа выглядит следующим образом: «Это любая комбинация кодовых точек Юникода, которую можно пройти одним нажатием клавиши со стрелкой влево или вправо на клавиатуре при идеальных обстоятельствах».
«при идеальных обстоятельствах» означает, что вы используете среду, которая, так сказать, действует как поиск в Google: то есть распознает, например, эмодзи (семья из 4 человек) или кластер графем (персонаж деванагари) как одну печатную персонаж.
3 вопроса:
1: Правильно ли приведенное выше определение того, что значит быть печатным символом в Юникоде?
2: Независимо от того, принимаете ли вы определение, знаете ли вы какой-либо список печатаемых символов, который охватывает используемые в настоящее время плоскости Unicode и возможные кластеры графем, а не только 100 символов ASCII, которые есть в строковой библиотеке Python (если бы у меня был такой список Думаю, я мог бы довольно легко создать шифр)?
3: Учитывая, что такой список не существует, и вы принимаете определение, как бы вы создали такой список, с помощью которого я мог бы создать шифр Цезаря, который мог бы шифровать любые / все печатные символы при следующих 4 условиях?
ПРИМЕЧАНИЕ: эти 4 условия - именно то, что, как мне кажется, требуется для правильного шифра Цезаря.
условие а
Зашифрованная строка будет действительной строкой utf8, состоящей из стандартных кодовых точек Unicode (без неназначенных или частных кодовых точек).
условие b
Зашифрованная строка также должна быть допустимой строкой utf8, состоящей из стандартных кодовых точек Unicode.
условие c
Вы должны иметь возможность перемещаться по зашифрованной строке, используя такое же количество штрихов клавишами со стрелками влево или вправо на клавиатуре, что и исходная строка (при идеальных обстоятельствах, как описано выше). Это означает, что и семейный эмодзи мужчина-женщина-мальчик-девочка, и символ деванагари при кодировании должны соответствовать ровно одному другому печатаемому символу, а не набору кодовых точек "несущества", которые клавиши со стрелками будут интерпретировать как разные символы. Это также означает, что один символ кодовой точки потенциально может быть преобразован в многоточечный символ и наоборот.
условие d
Как и в любом алгоритме шифрования / дешифрования, строка, которая должна быть зашифрована, и строка, которая была расшифрована (конечный результат), должны содержать одни и те же кодовые точки (две строки должны быть равны).
# Python 3.6:
import string
# build-in library
print(string.printable)
print(type(string.printable))
print(len(string.printable))
# length of the string (number of ASCII characters)
#perl6
use v6;
my @ordinals = <128104 8205 128105 8205 128103 8205 128102>;
#array of the family codepoints
@ordinals.append(<307 13 2325 2381 2359 2367 32 65279 127137>);
#add the other codepoints
my $result_string = '';
for @ordinals {
$result_string = $result_string ~ $_.chr;
}
# get a string of characters from the ordinal numbers
say @ordinals; # the list of codepoints
say $result_string; # the string
say $result_string.chars; # the number of characters.
say $result_string.comb.perl; # a list of characters in the string
результаты python:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ! "# $% & '() * +, -. / :;‹ =>? @ [] ^ _ `{|} ~
класс 'str'
100
perl6 результаты:
[128104 8205 128105 8205 128103 8205 128102 307 13 2325 2381 2359 2367 32 65279 127137]
????????????????ij क्षि ????
8
(«????????????????», «ij», «\ r», «क्», «षि», «», «», «????»). Seq