VIC шифр является одним из самых сложных и карандашных бумажных шифров когда - либо придуманные. Используемый в 1950-х годах советским шпионом Рейно Хайяненом под кодовым названием «ВИКТОР», его основным принципом является безопасность через запутывание; много запутывания.
Ваша задача - написать программу или функцию, которая будет принимать сообщение и кодировать его с помощью шифра VIC. Я также разместил здесь проблему с шифровальным декодером VIC . Если какая-либо из следующих инструкций неясна, не стесняйтесь спрашивать о них в комментариях. Инструкции адаптированы с этого сайта .
Кодирование шифра VIC
подготовка
Вам понадобится пять входов:
- текстовое сообщение
- короткое ключевое слово или фраза, содержащая наиболее распространенные буквы на вашем языке
- ключевая фраза, такая как цитата или строка из песни (не менее 20 символов)
- дата (или другое число, которое состоит из шести цифр или более)
- номер личного агента
На практике эти последние четыре должны быть предварительно согласованы отправителем и получателем, включая вопрос о том, используется ли номер агента отправителя или получателя в кодировании.
Мой пример сообщения будет: We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
Мы будем кодировать на английском языке (хотя вы можете использовать любой язык и алфавит), и наиболее распространенные буквы в английском алфавите A, E, I, N, O, R, S, T
. Я буду использовать ключевое слово SENATORI
.
Моя ключевая фраза - цитата Ричарда Фейнмана: «Первый принцип заключается в том, что вы не должны обманывать себя - и вы - самый легкий человек, чтобы обмануть».
В качестве даты я буду использовать 31 июля 2016 года (в формате 3172016
), то есть день, когда я написал это описание.
Личный номер, который я выбрал для себя 9
.
Краткое изложение шагов
- Получите промежуточные ключи для использования в следующих шагах.
- Построить и применить раскидистую шахматную доску.
- Построить и применить первую таблицу транспозиции.
- Построить и применить вторую (нарушенную) таблицу транспозиции.
- Завершите сообщение, вставив группу индикаторов сообщений.
Submechanisms
Еще две вещи, которые нужно объяснить, прежде чем мы углубимся в суть вопроса: процессы сложения цепочек и секвенирования.
Цепное сложение, также известное как отставший генератор Фибоначчи, работает, беря последовательность начальных цифр, добавляя первые две цифры без переноса (затем сложите их вместе mod 10
) и добавляя результат в конец. Например:
79081
7 + 9 = 6
790816
9 + 0 = 9
7908169
0 + 8 = 8
79081698
8 + 1 = 9
790816989
1 + 6 = 7
7908169897
... and so on
Последовательность - это, по сути, последовательность букв или цифр и их маркировка в алфавитном / числовом порядке. Дубликаты помечены слева направо. Например:
E X A M P L E
0 # A
1 0 2 # Es
1 0 3 2 # L
1 0 4 3 2 # M
1 0 4 5 3 2 # P
1 6 0 4 5 3 2 # X
3 3 0 5 8 4 2 0 4 7 5 4 8 1
0 1 # 0s
0 1 2 # 1
0 3 1 2 # 2
4 5 0 3 1 2 # 3s
4 5 0 6 3 1 7 8 2 # 4s
4 5 0 9 6 3 1 7 10 8 2 # 5s
4 5 0 9 6 3 1 7 11 10 8 2 # 7
4 5 0 9 12 6 3 1 7 11 10 8 13 2 # 8s
Я использую здесь нулевое индексирование, но индексирование, как вам нравится.
1. Промежуточные ключи
Разделите первые 20 букв ключевой фразы на две группы по 10 и секвенируйте каждую в отдельности, которую мы будем называть S1
и S2
.
THEFIRSTPR
S1: 8201357946
INCIPLEIST
S2: 2603751489
Выберите случайный 5-значный идентификатор сообщения M
(это может быть один из входных данных, если вы предпочитаете):
M = 47921
Вычтите без заимствования (вычтите mod 10
) первые пять цифр контрольной даты 3172016
из M
:
M 47921
date - 31720
= 16201
Цепочка добавить результат, пока у вас есть десять цифр:
1620178218
Добавьте эти цифры к S1
, без переноса или mod 10
, чтобы получить G
:
1620178218
S1 + 8201357946
G = 9821425154
Выше S2
напишите последовательность 0123456789. Найдите каждую цифру G
в последовательности 0123456789 и замените ее цифрой непосредственно под ней в S2
. Результат есть T
.
0123456789
S2 2603751489
G 9821425154
T 9806705657
Используйте цепочку, чтобы расширить T
до 60 цифр.
9806705657
becomes
980670565778637511245490262369939288595822106344304316978734
Эти последние 50 цифр в пяти рядах по десять цифр в каждом образуют U
блок.
T 9806705657
U 7863751124
5490262369
9392885958
2210634430
4316978734
Последние две неравные цифры U
блока по отдельности добавляются к личному номеру агента, чтобы задать ширину двух транспозиций, p
и q
.
9 + 3 = 12 (p, первая ширина транспонирования) 9 + 4 = 13 (q, вторая ширина транспонирования)
Упорядочить T
и использовать эту последовательность для копирования столбцов U
блока сверху вниз в новый ряд цифр V
.
T 9806705657
seqT 9804612537
U 7863751124
5490262369
9392885958
2210634430
4316978734
V 69911 56837 12548 26533 30206 13947 72869 49804 84323 75924
Упорядочить первые p
цифры, чтобы получить ключ для первой транспонирования K1
, и следующие q
цифры для ключа для второй K2
.
First 12 6 9 9 1 1 5 6 8 3 7 1 2
K1 6 10 11 0 1 5 7 9 4 8 2 3
Next 13 5 4 8 2 6 5 3 3 3 0 2 0 6
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
Наконец, секвенируйте последнюю строку U
блока, чтобы получить C
заголовки столбцов для трансграничной шахматной доски:
U5 4316978734
C 3105968724
2. Шатаясь шахматная доска
Сначала я приведу пример шахматной доски, а затем объясню принципы ее создания следующим образом:
3 1 0 5 9 6 8 7 2 4
S E N A T O R I
2 B D G J L P U W Y .
4 C F H K M Q V X Z #
Первая строка букв - это наше короткое ключевое слово SENATORI
. Ваше ключевое слово может быть любой строкой без дубликатов, но, поскольку оно определяет верхний ряд вашей шахматной доски, выбирайте мудро. Над ключевым словом находится C
, а остальные строки - остальная часть вашего алфавита в любом порядке, который вы выберете. В моем случае я заполнил шахматную доску остальным латинским алфавитом, знаком пунктуации .
и знаком для разграничения чисел #
. По сути, шахматная доска является причудливым шифром замещения. Например, «E» будет замещен 1
, а «W» будет заменен 27
.
После того, как мы закодировали наше текстовое сообщение с помощью этой шахматной доски, но сначала нам нужно сделать начало нашего сообщения менее очевидным, разбив его на случайную позицию и сделав все заглавными. Чтобы обозначить другое оригинальное начало, мы используем две точки остановки..
We are discovered. Take what you can. Burn everything else. Move to Safehouse Foxtrot 3.
становится
HING ELSE. MOVE TO SAFEHOUSE FOXTROT#3#.. WE ARE
DISCOVERED. TAKE WHAT YOU CAN. BURN EVERYT
Мы кодируем с помощью шахматной доски, давая нам:
407020 1293124 496481 96 354114062831 416479869443442424 271 581
2173436481812124 95451 274059 22628 435024 232880 14818229
Если длина сообщения не делится на 5, мы добавляем несколько нулевых символов для дополнения сообщения. Наше сообщение длиной 109 цифр, поэтому я добавлю один ноль: «4».
40702 01293 12449 64819 63541 14062 83141 64798 69443 44242 42715
81217 34364 81812 12495 45127 40592 26284 35024 23288 01481 82294
Примечание. Поскольку мое примерное сообщение не содержит цифр, я скажу здесь, что вы можете указать, скажем, как #3#
, что закодировано как 44344
здесь.
3. Первая транспозиция
Создайте таблицу транспонирования, написав K1
(из раздела «Промежуточные ключи»), а затем закодированное сообщение из предыдущего шага в строках одинаковой длины под ключом:
K1 6 10 11 0 1 5 7 9 4 8 2 3
4 0 7 0 2 0 1 2 9 3 1 2
4 4 9 6 4 8 1 9 6 3 5 4
1 1 4 0 6 2 8 3 1 4 1 6
4 7 9 8 6 9 4 4 3 4 4 2
4 2 4 2 7 1 5 8 1 2 1 7
3 4 3 6 4 8 1 8 1 2 1 2
4 9 5 4 5 1 2 7 4 0 5 9
2 2 6 2 8 4 3 5 0 2 4 2
3 2 8 8 0 1 4 8 1 8 2 2
9 4
Взяв пронумерованные столбцы в порядке их номеров, мы получим:
060826428 246674580 151411542 246272922 961311401 082918141
4414434239 118451234 334422028 293488758 0417249224 794943568
4. Вторая транспозиция
Первая транспозиция была относительно простой. Этот, однако, является нарушенным транспонированием. Схема разрушения определяется шириной таблицы и ключа. В нашем примере у нас есть 110 цифр и 13 столбцов, что означает, что у нас будет 8 полных строк и 6 остатков. Мы начинаем заполнять первый ряд, но останавливаемся в столбце 0 и продолжаем следующим образом:
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 stop at 0
2 4 6 6 7 4 5 8 0 1 continue in a triangle pattern
5 1 4 1 1 5 4 2 2 4 6
2 7 2 9 2 2 9 6 1 3 1 1
4 0 1 0 8 2 9 1 8 1 4 1 4 until the end
4 1 4 4 3 4 2 3 9 1 1 restart and stop at 1
8 4 5 1 2 3 4 3 3 4 4 2
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 restart and stop at 2
Затем мы заполняем последние несколько пробелов оставшимися цифрами.
K2 8 7 12 2 10 9 4 5 6 0 3 1 11
0 6 0 8 2 6 4 2 8 7 2 4 9
2 4 6 6 7 4 5 8 0 1 2 2 4
5 1 4 1 1 5 4 2 2 4 6 7 9
2 7 2 9 2 2 9 6 1 3 1 1 4
4 0 1 0 8 2 9 1 8 1 4 1 4
4 1 4 4 3 4 2 3 9 1 1 9 4
8 4 5 1 2 3 4 3 3 4 4 2 3
2 0 2 8 2 9 3 4 8 8 7 5 8
0 4 1 5 6 8
Теперь мы зачитываем столбцы точно так же, как мы это делали при первом транспонировании.
71431148 42711925 861904185 22614147 45499243 28261334 80218938
641701404 025244820 645224398 271283226 94944438 064214521
И разбить все на 5-значные группы:
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189
38641 70140 40252 44820 64522 43982 71283 22694 94443 80642 14521
5. Завершите сообщение
Последний шаг - вставить наш случайный идентификатор 47921
сообщения в само сообщение. Последняя цифра контрольной даты 6
указывает расстояние, которое группа должна быть от конца.
71431 14842 71192 58619 04185 22614 14745 49924 32826 13348 02189 38641
70140 40252 44820 64522 43982 47921 71283 22694 94443 80642 14521
Примечания к этой проблеме
- Вам предоставляется как минимум пять входных данных: сообщение, ключевое слово буквы, ключевая фраза, дата и личный номер. Вы можете включить два дополнительных ввода: идентификатор случайного сообщения и нули, необходимые для заполнения сообщения, или ваша функция может генерировать некоторые случайные числа самостоятельно.
- Можно предположить, что все входные данные верны, с правильным количеством цифр и букв (5-значный идентификатор сообщения, не менее 20 цифр для ключевой фразы и т. Д.). Вы можете предположить, что в ваших строках (сообщение и ключевые слова) уже удалены все знаки препинания и пробелы, кроме тех, которые вы разрешаете в своей версии, и что числа уже обозначены знаками чисел.
- В первом ключевом слове не должно быть повторяющихся букв, и в вашем коде вы можете предполагать, что в нем никогда не бывает повторяющихся букв.
- Язык, который вы используете для кодирования, не имеет значения, поскольку язык уже существует, алфавит уже существует, и вы указываете, какой язык вы используете в своем ответе.
- Какой бы алфавит вы ни использовали для своей шахматной доски, вы можете добавлять или удалять символы, чтобы дополнить шахматную доску. Укажите, для чего вы используете эти символы (например, знаки препинания, отдельный символ «начало сообщения», символы для общих слов). Вы можете полностью отказаться от знака числа и прописать числа или включить каждую цифру в шахматную доску, используя слот, где знак числа был для чего-то другого. Пожалуйста, укажите, какую шахматную доску вы использовали в своем ответе.
- Выходные данные должны быть либо строкой пятизначных групп, разделенных пробелами, списком пятизначных целых чисел или чем-то подобным.
- Я использовал нулевую индексацию и
0123456789
в моем примере. Вы можете использовать 1-индексирование и /1234567890
или другую систему в своем ответе, если вы укажете, что вы использовали.
Вот пример реализации на Ideone .
Это длинный пост, и я написал большую часть его вручную, поэтому, если в этом посте есть какие-то запутанные части или ошибки в подсчете и транспонировании, пожалуйста, дайте мне знать. Удачи и хорошего гольфа!
источник
adding the first two digits without adding
Ты имеешь в виду ношение?without borrowing
иwithout carrying
? Вы имеете в виду сложение и вычитание мода10
, т.е.(6+7) mod 10 = 3
и(6-8) mod 10 = 8
?Ответы:
Питон 3 ,
14231348132413161300128612501249120912061204 байтаЭто, безусловно, самый длинный гольф, который я когда-либо делал, и единственный гольф, где меня всерьез беспокоило, когда у меня заканчиваются односимвольные переменные имена. Предложения по игре в гольф приветствуются. Попробуйте онлайн!
Я кодирую заглавными буквами латинского алфавита с дополнительными символами
.
и#
, используя 0-индексирование и0123456789
при преобразованииg
вt
. Моя шахматная доска имеет формат, подобный следующему примеру:Изменить: -63 байта благодаря предложению TuukkaX сократить некоторые из часто используемых функций с однобуквенными переменными. -12 байт от
a, g, t
более компактных.Изменить: -24 байта от создания путем удаления имен переменных для промежуточных ключей, которые используются только один раз, а именно
a, g, s, S, k, K
.Изменить: -74 байта от консолидации
H(), T() and C()
.Редактировать: -1 байт, спасибо Нику А за предложение перейти
ord(s[i])+ord(s[i+1])
наsum(map(ord,s[i:i+2]))
. -2 байта от изменения 2+=[a]
вызовов на+=a,
. -13 байтов от измененияG()
найденного индекса минимумаs
. -2 байта от измененияy=(y+1)%v
доy=-~y%v
. -15 байт от назначенияk.index()
доK
. -4 байт от назначения10
доW
. -5 байтов от присвоения1-I(d[-1])
кX
внутреннейV
. -3 байта от переписыванияC()
основного цикла. -2 байта от реорганизацииT()
.Ungolfing:
источник
ord(seq[i])+ord(seq[i+1])
кsum(map(ord,seq[i:i+2]))
сохраняет 1 символ я верю.С
288027692766276227432741273926992458 байтБоже мой. Это самая длинная программа я когда - либо имел в гольф. Это также первый случай, когда у меня фактически закончились односимвольные имена переменных для глобальной области видимости, поэтому мне пришлось перейти к использованию двухсимвольных (тот факт, что я, очевидно, не могу переопределить переменные, не помогает). Поэтому советы по гольфу очень ценятся.
Ungolfed
Компилируется без каких-либо предупреждений, в отличие от версии для гольфа. Незначительные изменения, внесенные в версию для гольфа, не будут отражены в этой версии без гольфа.
Примечания
Для кодирования сообщения используется шахматная доска, подобная следующей:
Это предполагает, что все применимые строки приведены в верхнем регистре. В сообщении также должны быть удалены все знаки препинания, кроме точек и всех чисел
#
, обозначенных s, в то время как ключевая фраза должна содержать все знаки пунктуации удалены.Полученное закодированное сообщение выводится в STDOUT в виде строки разделенных пробелами пятизначных групп.
Входное сообщение должно быть на английском языке.
Я бы объединил несколько функций, которые использовал, но тогда мне пришлось бы прибегнуть к использованию двухбуквенных имен переменных, что сделало бы окончательную программу длиннее, чем было бы, с несколькими дополнительными функциями.
В настоящее время это не предполагает, что ключевое слово (по крайней мере, на английском языке) всегда будет содержать один и тот же набор букв, и поэтому восполняет это, удаляя дубликаты, манипулируя шахматной доской и т. Д. Эта возможность, очевидно, не требуется OP, таким образом, я в настоящее время играю в гольф от лишних, ненужных байтов, которые занимают.Обновлено для игры в гольф.источник
JavaScript (ES6),
946938953 байтаВ выходные я видел, что для этого еще не было записи в JS, так что вот моя (последняя минута) попытка. Внедрение и игра в гольф это было так же безумно, как было весело!
Демо-фрагмент
Показать фрагмент кода
Изменить: -8 байт
Понял, что были дополнительные скобки вокруг функции
S,J,A,Q
Изменить: +15 байт
Обновлена логика
message id
размещения символа в последнем сообщении (теперь 1 индексируется, а 0 не включает его в вывод).Ungolfed
Примечания
Для кодирования сообщения используется шахматная доска, подобная следующей:
Все строки указаны в верхнем регистре. Сообщение имеет буквенно-цифровую латиницу (плюс
.
и#
), и все знаки препинания (кроме точек) должны быть удалены. Все числа уже должны быть отмечены с#
. В ключевой фразе должны быть удалены все знаки препинания / пробелы.Полученное сообщение возвращается в виде массива из 5-значных строк.
Улучшения
Я чувствую, что есть способ злоупотребить "Все языки", чтобы сохранить некоторые байты. Если бы у меня было больше времени, я бы изменил это так, чтобы предположить, что этот язык похож на гавайский, в котором всего 12 букв.
Любые предложения по гольфу всегда приветствуются.
источник
message identifier
кажется, что7
далеко от конца, а не6
. Кроме того, в вашей версии без гольфа то же самое,Id
кажется,6
далеко от начала, а не до конца.1
означает самый конец, куда, по вашему мнению,message identifier
должен идти0
? Я могу изменить это, мне просто нужно знать.0
message identifier
Clojure,
11971212 байтО, я измотан.
Обновление: добавлено требуемое место случайного разбиения сообщения, версия без заглавных букв использует то же место, что и в приведенном примере, так что алгоритм может быть легко проверен.
Образцы входных данных и контрольный пример:
Ungolfed:
У него есть альтернативная реализация на шахматной доске,
B
такая же, как в определении задачи. Но в представлении используется другой, в котором неиспользуемые алфавиты сначала заполняют 2-ю строку, а затем 3-ю вместо столбцов за столбцом.источник
coords
генерируется дважды, сначала генерируя треугольную форму, а затем заполняя любые отсутствующие координаты. Кроме того, «дополнение к длине умножения N» может иметь более элегантное решение, чем объединение N - 1 элементов и разбиение на длины N.(split-at 49 mymsg)
49, что-то вроде этого,(rand-int(count mymsg))
поэтому правильный ответ будет чуть более 1200 байтов. zzz