Цезарь со всеми печатными символами Юникода - PullRequest
0 голосов
/ 19 января 2019

Я хочу создать шифр Цезаря, который может кодировать / декодировать печатаемые символы Юникода (кластеры графемы с одним и несколькими кодами, смайлики и т. Д.) Из всего Юникода (за исключением области частного использования). Предпочтительно, он будет использовать список всех печатных символов.

ПРИМЕЧАНИЕ. Несмотря на то, что я хочу создать шифр Цезаря, на самом деле речь идет не о шифровании. Вопрос в том, чтобы исследовать свойства юникода.

Я нашел эти вопросы:

Каков диапазон печатаемых символов Юникода?

Шифр ​​со всеми символами Юникода

Но я не получил ответа на то, что я хочу.

Примечание: Если вы даете кодовый ответ, меня больше всего интересует решение, которое использует либо python3, либо perl6, так как они являются моими основными языками.

Недавно мне дали задание написать шифр Цезаря, а затем кодировать и декодировать текст на английском языке.

Я решил это в python, используя встроенную константу string.printable библиотеки строк. Вот распечатка константы: (Я использовал визуальный студийный код)

[см. Код и результаты Python ниже]

Документация гласит: «»» Строка символов ASCII, которые считаются печатными. Это комбинация цифр, символов ascii_, знаков пунктуации и пробелов. «»» https://docs.python.org/3.6/library/string.html#string-constants

Мне интересно, как вы могли бы создать Цезарь-шифр, который мог бы кодировать / декодировать все возможные печатаемые символы, которые вы можете сделать из кодовых точек Юникода (просто предположите, что у вас есть все необходимые шрифты, чтобы увидеть те, которые должны быть видны на экране).

Вот мое понимание того, что это значит для что-то, что будет печатным персонажем:

Когда я беру строковую константу python выше, и пройти его с помощью клавиш со стрелками влево или вправо на клавиатуре, мне нужно ровно 100 ударов, чтобы получить до конца (столько же, сколько символов). Похоже, что есть один-к-одному соответствие между печатным символ и быть перемещаемым одним нажатием клавиши со стрелкой.

Теперь рассмотрим эту строку:

"????ij 10 ? "

На основании константы питонов string.printable, Мне кажется, эта строка состоит из следующие 7 печатных символов: (вы можете посмотреть отдельные кодовые точки по адресу: https://unicode -table.com / ru / )

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/) (кодовые точки кажутся скорее шестнадцатеричными, чем цифрами)

(Space) кодовая точка: 32

(пространство без перерывов с нулевой шириной) кодовая точка: 65279 (AKA U + FEFF BYT ORD MARK (спецификация)) (https://en.wikipedia.org/wiki/Byte_order_mark)

(игральная карта Ace of Spades) ? кодовая точка: 127137

Когда я вставляю это вставьте в блокнот и попробуйте пройти его с помощью клавиши со стрелкой, В итоге я использую 10 клавиш, а не 7, потому что семья смайликов нужна 4 нажатия клавиш (вероятно, потому что блокнот не может справиться с Zero Width Joiner, кодовая точка: 8205, и, конечно, блокнот не может отображать семейный глиф). С другой стороны, когда я публикую строку в поиске Google, я могу пройти всю строку с 7 ударов.

Затем я попытался создать строку в Perl6, чтобы увидеть, что графема Perl6 осознание сделает из строки:

(я использую редактор Atom)

[см. Код perl6 и результаты ниже]

perl6 считает, что символ Деванагари кши क्षि (4 кодовых точки) на самом деле 2 графемы, каждая с 2 кодовыми точками. Даже если он может быть представлен в виде двух символов, как видно из приведенного выше списка, Я думаю, что это ошибка. Perl6 должен быть графемным в курсе, и еВ моем блокноте Windows (и в поиске Google) он представляет собой один графем / символ.

На основе двух строк практическое определение печатного символа выглядит следующим образом: «Это любая комбинация кодовых точек Юникодаэто может быть пройдено одним нажатием клавиши со стрелкой влево или вправо на клавиатуре при идеальных обстоятельствах ».

« при идеальных обстоятельствах »означает, что вы используете среду, которая, так сказать, действует как поиск GoogleТо есть он распознает, например, эмодзи (семью из 4 человек) или кластер графем (символ деванагари) как один печатный символ.

3 вопроса:

1: Это вышеточное определение того, что значит быть печатным символом в юникоде?

2: Независимо от того, принимаете ли вы определение, знаете ли вы какой-нибудь список печатных символов, которые охватывают используемые в настоящее время плоскости Юникода и возможную графемукластеры, а не только 100 символов ASCII, которые есть в библиотеке строк Python (еслиУ меня был такой список, я думаю, я мог бы создать шифр довольно легко)?

3: Учитывая, что такого списка не существует, и вы принимаете определение, как бы вы пошли на создание такого списка, с помощью которогоЯ мог бы создать шифр Цезаря, который мог бы зашифровать любые / все печатаемые символы, учитывая следующие 4 условия?

ПРИМЕЧАНИЕ: эти 4 условия - это то, что, как мне кажется, требуется для правильного шифра Цезаря.

условие a

Зашифрованная строка будет допустимой строкой utf8, состоящей из стандартных кодовых точек Unicode (без присвоенных или кодовых точек области личного использования)

условие b

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

условие c

Вы должны иметь возможность проходить зашифрованную строку, используя одинаковое количество ударов влево или вправоклавиши со стрелками на клавиатуре как исходная строка (с учетом идеальных обстоятельств, описанных выше).Это означает, что как смайлики семьи мужчина-женщина-мальчик-девочка, так и символ деванагари, при кодировании, должны соответствовать точно одному другому печатному символу, а не набору кодов «отсутствия», которые клавиши со стрелками будут интерпретировать как разные символы.Это также означает, что один символ кодовой точки потенциально может быть преобразован в символ с множеством кодов и наоборот.

условие d

Как и в любом алгоритме шифрования / дешифрования, строка, которая должна быть зашифрована истрока, которая была расшифрована (конечный результат), должна содержать точно такие же кодовые точки (2 строки должны быть равны).

# 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 results:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRZUUW $Y& '() * +, -. / :; <=>? @ [] ^ _ `{|} ~

класс' str '

100

perl6результаты:

[128104 8205 128105 8205 128103 8205 128102 307 13 2325 2381 2359 2367 32 65279 127137]

?‍?‍?‍?ij क्षि ?

8

("?‍?‍?‍?", "ij", "\ r", "क्", "षि", "", "", "?"). Seq

1 Ответ

0 голосов
/ 20 января 2019

TL; DR Я думаю, что ваш вопрос обоснован и заслуживает лучшего ответа, чем тот, который я написал до сих пор.Давайте поговорим.


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

Но если ваша цель на самом деле "исследовать свойства Unicode"вместо того, чтобы создавать шифр, тогда, по-видимому, это не имеет значения.

И, конечно, я мог просто испытывать недостаток воображения или просто неспособность понять Unicode, несмотря на то, что потратил годы на борьбу с ним.

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

"Шифр Цезаря со всеми печатными символами Юникода"

Это чистая формулировка, которая у вас есть в заголовке.

Единственные проблемные части - "Цезарь", "шифр "," все "," Unicode "," для печати "и" символы ".Давайте пройдемся по ним.

Шифр ​​Цезаря

Шифр ​​Цезаря - это особенно простой шифр с одним алфавитом.Unicode - это не один большой алфавит.Но, возможно, вы могли бы обработать подмножество его кодовых точек, как если бы они были.

Я бы сказал, что это то, о чем был SO Шифр ​​со всеми символами Unicode .

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

Игнорирование вашего приоритета в исследовании свойств Unicode будет иметь смысл, если вы вместо этого согласитесь наобычный шифр ASCII.Или, возможно, вернитесь к этому Шифру со всеми символами Unicode SO и выберите, где они остановились, возможно, отметив, что согласно комментарию к этому SO они, очевидно, остановились только на BMPплоскость:

Обратите внимание, что вы используете только кодовые точки BMP (т.е. от U + 0000 до U + FFFF).Юникод варьируется от U + 0000 до U + 10FFFF, поэтому вам не хватает около миллиона кодовых точек:)

Так что, возможно, вы могли бы добиться большего.Я не думаю, что это было бы целесообразно с точки зрения создания шифра для самого себя, но это может быть для того, чтобы узнать больше о свойствах Unicode.

Cipher

@ TomBlodget в их комментарий к вашему вопросу отмечает, что:

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

Если вы хотите универсальное решение для шифра Unicode, следуйте рецепту Тома.

Все

В комментарии к вашему вопросу о количестве графем @nwellnhof отметил, что:

существует бесконечное число

Но вы тогдатакже вполне разумно ответил, что в любом данном тексте будет только конечное число;намерение Unicode заключается в том, что совместимое с Unicode программное обеспечение может / будет генерировать результаты mojibake, если дан вырожденный ввод (где то, что считается вырожденным, несколько открыто для уточнения в обновлениях Unicode);и это основа, на которой вы надеетесь продолжить.

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

Я действительно должен вставить некоторые вычисления здесь, чтобы наложить некоторые ограничения на проблему.«Фактически бесконечен» триллион?Зачем?Что-то в этом роде.Но прежде чем углубляться в это, я буду ждать комментариев.

Давайте представим, что это триллион, и это не проблема, и продолжим.

Unicode

Юникод чрезвычайно сложен.

Вам было дано задание на создание шифра Цезаря, очень простая вещь.

Они действительно не очень хорошо смешиваются, если вы не склонны сильно хранитьвсе просто.

Но вы хотите исследовать свойства Unicode.Так что, возможно, вы хотите вникнуть во все сложности.Но тогда возникает вопрос: сколько лет вы хотите потратить на изучение последствий вскрытия ящика этой пандоры?(Я изучал Unicode и выключал его в течение десяти лет. Это сложно.)

Printable

Вы связались с SO-вопросом "Каков диапазон печатных символов Unicode?".Это включает в себя ответ, который отмечает:

Чем больше вы узнаете о Юникоде, тем больше понимаете, насколько неожиданно разнообразны и непостижимо странные человеческие системы письма.В частности, не всегда очевидна возможность печати определенного «символа».

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

Символы

Учитывая, что ваша цель состоит в том, чтобы написать шифр Цезаря, шифр, который использовался тысячи лет назад и который воздействует на персонажей, имеет смысл, что вы сосредоточились напользователь считает символом ".

Per определение Unicode , это называется" графема ".

Один из ваших примеров символов дает понять, насколько проблематично различиенаходится между «тем, что пользователь считает символом» (графемой) и кодовой точкой (то, что Python считает символом):

print('क्षि'[::-1])
िष्क

Это показывает искажение одного «символа» (одногографема) написано в Деванагари, который, согласно Википедии, «одна из самых используемых и принятых систем письма в мире».

(Или, если мы хотим игнорировать половинуПланета, на которую эта калечащая сила воздействует все чаще и чаще, фокусируется только на людях, которые думали, что они в безопасности:

print('??'[::-1])
??

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

Графемы

Итак, вы вполне разумно подумали: «Может быть, Perl 6 поможет».

Цитировать UAX # 29 , документ Приложения Unicode по "Сегментации текста Unicode":

Этот документ определяет спецификацию по умолчанию для кластеров графем.

Perl 6реализовал механизм кластеризации графемы.В принципе, он может кластеризоваться различными способами, но на данный момент реализована спецификация по умолчанию.Это то, что позволяет Perl 6 избежать ошибок, допущенных Python в приведенном выше.

Но документ Unicode продолжается:

[спецификация для кластеров графем] может быть настроена для конкретных языков, операции или другие ситуации.

Таким образом, вы не можете просто просмотреть текст (или передать его некоторому программному обеспечению) и сказать, какие «символы» он содержит, если под «символом» вы подразумеваете «что»пользователь воспринимает это как символ ".

Становится хуже ...

Нажатия клавиш

" ?‍?‍?‍?ij क्षि ? "... блокнот ... 10 нажатий клавиш ... поиск в Google ... 7 нажатий ... Perl6 ... Редактор Atom ... Perl6 думает क्षि ... на самом деле это 2 графемы ... Я думаю, что это ошибка... блокнот (и поиск в Google) считает, что это одна графема / символ

Для поиска Google требуется 10 тыс.Удары глаз - потому что это связано не с поиском в Google, а с аспектами моей системы, в том числе с тем, какой веб-браузер я использую (Firefox), и другими деталями.

Некоторые редакторы могут быть настроены так, чтобы курсоры над ними क्षि'(или' fi ') будет 1 или 2 нажатиями клавиш, в зависимости от того, как вы их конфигурируете и / или на каком языке вы указываете текст, на котором написан. Для меня, редактирование этого SO ответа с помощью Firefox на Linux Mint, требует 2 нажатий клавишчтобы навести курсор на क्षि.

Perl 6 правильно сообщает результат .chars для 'क्षि' как 2 по умолчанию, потому что это то, что Unicode говорит, что это согласно спецификации кластеризации графем по умолчанию.(«Расширенные кластеры графем».) Это соответствует тому, что Firefox в Linux Mint редактирует этот SO-ответ, потому что звезды выстраиваются в ряд и наступает воскресенье.

Блокнот или другое программное обеспечение разумно требует всего одного нажатия клавиши, чтобы навести курсор на क्षिв то время как другие редакторы разумно берут два, потому что оба приемлемы в соответствии со спецификацией Unicode:

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

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

Ваши вопросы

1: является ли приведенное выше точное определение того, что означает быть печатаемым символом вUnicode?

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

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

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

И любое небольшое подмножество, которое кто-либо может создать, не будет каноническим, потому что консорциум Unicode не благословит его, и народ будет спорить о том, что должно быть включено.

3: ... как бы вы могли создать такой список, с помощью которого я мог бы создать шифр Цезаря, который мог бы шифровать любой / все печатаемые символы при следующих 4 условиях?

Во-первых, ваши условияслишком напряженный.См. Следующий раздел.

Но даже если вы отбросите слишком сложные, это все равно будет слишком сложно, а результат слишком неинтересен, чтобы делать что-то стоящее.

4: Если вы думаете, что создание такого списка - ужасная идея, как бы вы создали шифр?

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

Ваши условия

Зашифрованная строка будет допустимой строкой utf8, состоящей из стандартных кодовых точек Unicode (без неназначенныхили кодовые точки области личного использования)

Это должно быть больше ограничено чем то, но разумно сказать, что это должна быть допустимая строка Unicode.Если вы хотите настаивать на том, что это utf8, это тоже хорошо.

Зашифрованная строка также должна быть допустимой строкой utf8, состоящей из стандартных кодовых точек Юникода

Конечно.

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

Это может быть для небольшого подмножества символов Юникода.Но ...

Это означает [одно нажатие клавиши как для исходной, так и для кодированной версии] символа деванагари [क्षि]

... не является разумным требованием.

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

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

Это будет нелепое количество боли.И для нуля или, самое большее, крошечного, усиления.

строка, которая должна быть зашифрована, и строка, которая была расшифрована (конечный результат), должна содержать точно такие же кодовые точки (2 строки должны быть равны).

Итак, нормализации нет.

Это исключает все полезные свойства Perl 6.

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

Заключение

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

...