Расшифруйте зашифрованный текст Vigenère


28

Виженера Шифр был простым полиалфавитным шифром , который в основном применяется один из нескольких шифров Цезаря, в соответствии с ключом. В основном буквы в ключе указывают, какой сдвинутый алфавит использовать. Для этого был простой инструмент, называемый квадратом Вигенера:

введите описание изображения здесь

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

Предположим, мы хотим зашифровать строку CODEGOLF. Нам также нужен ключ. В этом случае ключ должен быть FOOBAR. Когда ключ короче открытого текста, мы расширяем его повторением, поэтому фактический ключ мы используем FOOBARFO. Теперь посмотрим на первую букву ключа, который Fдолжен найти алфавит. Это начинается, возможно неудивительно, с F. Теперь мы находим столбец с первой буквой открытого текста и получающейся буквой H. Для второй буквы мы имеем Oв качестве ключевой буквы и буквы в виде простого текста, в результате чего C. Продолжая в том же духе, мы наконец получаем HCRFGFQT.

задача

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

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

Построение квадрата Вигенера по-прежнему очень похоже, и шифр работает по-прежнему. Просто немного ... громоздко давать здесь в полном объеме.

вход

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

Выход

Одна строка, содержащая расшифрованное сообщение.

Выигрышное условие

Поскольку шифрование иногда рассматривается как оружие, код должен быть коротким, чтобы облегчить контрабанду. Чем короче, тем лучше, так как это снижает вероятность открытия.

Пример ввода 1

Key
miQ2eEO

Пример вывода 1

Message

Пример ввода 2

ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu

Пример вывода 2

ThisWorksEquallyWellWithNumbers123894576

Прошла неделя На данный момент самое короткое решение принято. Для тех, кто заинтересован, в нашем конкурсе были представлены следующие материалы и продолжительность:

130 - Python
146 - Haskell
195 - C
197 - C
267 - VB.NET

И наши собственные решения, которые не были ранжированы с другими:

108 - Ruby
139 - PowerShell


Кажется, что это может быть полезно для печати квадрата Vigenère.
Эрик Outgolfer

Ответы:


10

Golfscript - 48 символов

n%~.,@*\{\(123,97>91,65>+58,48>+:|?@|?\-|=}%\0<+

Никаких хитростей в этом!


+1 Я лег спать, думая, что должен быть способ уменьшить это до ~ 50, теперь я вижу, что это возможно, но я, вероятно, не справился бы с этим в ближайшее время
gnibbler

8

16-битный файл MS-DOS .COM - 87 байт

Двоичный кодированный Base64 ( по этой ссылке для декодера )

v1cBi8/oQACJ/ovv6DkAi9msitAqF3MDgMI+gMJhgPp6dguA6jqA+lp2A4DqK80hO/d0IkM563TW69YsYXMIBCB9AgQrBBqqtAHNITwNdev+xLIKzSHD

Обычно вы сами пишете короткий исходный код для игры в гольф. Хотя, вероятно, не невозможно, я как-то сомневаюсь в этом.
Джои

@Joey: Что, ты никогда не сдавал инструкции машинного кода! Чему они учат молодежь в эти дни! ;-)
Skizz

Скизз: я сделал. Хотя не в Base64;) (у нас был класс несколько лет назад, когда нам приходилось писать программы для Siemens 80C167 на ассемблере - и на экзаменах также собирать их в машинный код. Я думал о том, чтобы выкопать эти знания для ассемблера Задача Quine, но у нас не было средств вывода [по крайней мере, они менялись]).
Джои

@Joey: Base64 - это просто удобство для других пользователей на этом сайте, его легко декодировать и сохранять в виде бинарного файла (такая возможность есть в ссылке в ответе).
Skizz

Ааа, простите Я думал, что вы бы дали длину Base64. Ну, Крис однажды включил в решение произвольные символы и просто дал hexdump помимо своего ответа. Я сделал подобное в прогнозе погоды.
Джои

8

APL (45)

∆[⍙⍳⍨¨⌽∘∆¨(⍴⍙←⍞)⍴1-⍨⍞⍳⍨∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26]

Объяснение:

  • ∆←⎕D,⍨⎕A,⍨⎕UCS 96+⍳26: сгенерировать алфавит (цифры ( ⎕D) следуют за буквами ( ⎕A) следуют за строчными буквами ( ⎕UCS 96+⍳26значения Юникода от 97 до 122).

  • 1-⍨⍞⍳⍨∆: прочитать строку (ключ), найти положение каждого символа в алфавите и вычесть один (массивы по умолчанию основаны на единицах, поэтому смещение по этим значениям напрямую сместит алфавит на единицу слишком далеко).

  • (⍴⍙←⍞)⍴: прочитайте другую строку (сообщение) и повторите индексы ключа так, чтобы он соответствовал длине сообщения.
  • ⌽∘∆¨: повернуть алфавит по индексам, принадлежащим клавише
  • ⍙⍳⍨¨: поиск каждого символа в сообщении в соответствующем смещенном алфавите
  • ∆[... ]: поиск данных индексов в обычном алфавите с указанием соответствующих символов.

6

Рубин - 132 127 122 109 100 знаков

a,b=*$<
c=*?a..?z,*?A..?Z,*?0..?9
(b.size-1).times{|i|$><<c[c.index(b[i])-c.index(a[i%(a.size-1)])]}

Используйте *$<вместо $<.to_aи встроенную лямбду, чтобы сохранить еще несколько байтов. - Вентеро 5 минут назад
Джои

Спасибо @Joey, я вытащил эту лямбду, чтобы спасти персонажей и почему-то упустил, что это на самом деле дороже.
Nemo157

5

Питон - 122 символа

from string import*
L=letters+digits
R=raw_input
K,T=R(),R()
F=L.find
print"".join(L[F(i)-F(j)]for i,j in zip(T,K*len(T)))

5

J, 65 знаков

v=:4 : 'a{~x(62|[:-/"1 a i.[,.#@[$])y[a=.a.{~62{.;97 65 48+/i.26'

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

Использование:

   'miQ2eEO' v 'Key'
Message
   'CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu' v 'ThisIsAKey'
ThisWorksEquallyWellWithNumbers123894576

4

Perl, 95 символов

Perl 5.010, работает с perl -E:

%a=map{$_,$n++}@a=(a..z,A..Z,0..9);@k=<>=~/./g;
$_=<>;s/./$a[($a{$&}-$a{$k[$i++%@k]})%62]/ge;say

3

Python - 144 143 140 136 125 символов

Наверное, не самый лучший, но эй

from string import*
l=letters+digits
r=l.find
q=raw_input
k=q()
print"".join(l[(r(j)-r(k[i%len(k)]))%62]for i,j in enumerate(q()))

Да, я собирался опубликовать что-то подобное. Вы можете назначить raw_input переменной, 3 или около того символа.
Хуан

3

Golfscript - 65 символов

Еще нужно больше играть в гольф. А пока T - это текст, K - это ключ, L - список букв.

n%):T,\~*:K;''26,{97+}%+.{32^}%10,{48+}%++:L;T{L\?K(L\?\:K;-L\=}%

3

К, 81 61

k:0:0;,/$(m!+(`$'m)!+{(1_x),1#x}\m:,/.Q`a`A`n)[(#v)#k]?'v:0:0

,

k)k:0:0;,/$(m!+(`$'m)!+{(1_x),1#x}\m:,/.Q`a`A`n)[(#v)#k]?'v:0:0
ThisIsAKey
CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu
"ThisWorksEquallyWellWithNumbers123894576"

2

Perl, 115 символов

$a=join'',@A=(a..z,A..Z,0..9);$_=<>;chop;@K=split//;$_=<>;s/./$A[(index($a,$&)-index($a,$K[$-[0]%@K]))%@A]/ge;print

2

Golfscript - 92 персонажа

n%~\.,:l;{0\{1$+\)\}%\;}:&;26'a'*&26'A'*&+10'0'*&+\@.,,{.l%3$=4$?\2$=4$?\- 62%3$\>1<}%\;\;\;

Вероятно, намного дольше, чем нужно. Все еще пытаюсь разобраться с GS.

Вот "неопрятная" и прокомментированная версия

n%~\.,:l;
{0\{1$+\)\}%\;}:&; # This would be sortof an equivalent for range applied to strings
26'a'*&26'A'*&+10'0'*&+\@., # This mess generates the dictionary string,
# l = len(key)
# 0 dictionary (letters + digits)
# 1 key
# 2 text
{
    # 3 index
    .   #+1 Duplicate the index

    # Find the index of the key letter
    l%  #+1 Indice modulo key
    3$  #+2 Duplicate the key
    =   #+1 Get the key letter
    4$? #+1 Search the letters index

    # Find the index of the text letter
    \   #+1 Get the index
    2$  #+2 Get the text
    =   #+1 Get the text letter
    4$? #+0 Search the letters index

    # 3 key index
    # 4 letter index

    \-   #+1 get the index of the new letter

    62% #+1 wrap the index around the dictionary

    3$ #+2 Get the dictionary

    \> #+1 remove the first part of the dict around the target letter

    1< #+1 remove everythin after 
}%
\;
\;
\;

2

VBA, 288

Не совсем превосходит перечисленные баллы VB.NET (но я уже близко):

Sub h(k,s)
v=Chr(0)
Z=Split(StrConv("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",64),v)
a=Split(StrConv(s,64),v):b=Split(StrConv(k,64),v)
For l=0 To Len(s)-1
j=l Mod Len(k)
g=0
For i=0 To 62:g=g+i*((Z(i)=b(j))-(Z(i)=a(l))):Next
x=x &Z(IIf(g<0,g+62,g))
Next
s=x
End Sub

Использование:

Sub test()
k = "ThisIsAKey"
s = "CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu"
h k, s
MsgBox s
End Sub

Спасибо Джои за подсказку!


g=g+IIf(Z(i)=c,i,0)-IIf(Z(i)=d,i,0)был бы один кандидат, которого я могу определить. Также как и проверка того, понимают ли окончания строки LF VBA. x=x & Z(g)Полагаю, по крайней мере, один пробел тоже может быть пропущен.
Джои

Другой способ написания строки: g=g+i*((Z(i)=d)-(Z(i)=c)) (потому что True-1 в VB). Может быть, это работает.
Джои

Спасибо за отзыв, @Joey. Я поищу любые другие улучшения и добавлю это.
Gaffi

2

С, 186

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

char a[99],*s,*t;k,j;main(int m,char**v)
{for(;j<26;++j)a[j]=32|(a[j+26]=65+j),
a[52+j]=48+j;while(*v[2])
putchar(a[s=strchr(a,v[1][k++%strlen(v[1])])
,t=strchr(a,*v[2]++),s>t?t-s+62:t-s]);}

Непрерывные линии

char a[99],*s,*t;k,j;main(int m,char**v){for(;j<26;++j)a[j]=32|(a[j+26]=65+j),a[52+j]=48+j;while(*v[2])putchar(a[s=strchr(a,v[1][k++%strlen(v[1])]),t=strchr(a,*v[2]++),s>t?t-s+62:t-s]);}

Обсуждение процесса игры в гольф этого кода можно найти здесь: http://prob-slv.blogspot.com/2013/04/code-golf.html


2

JavaScript 248

var v= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
function d(k,c){var a,b,o,x
a=k.charAt(0)
x=v.indexOf(a)
b=v.substr(x)+v.substring(0,x)
o= v.charAt(b.indexOf(c.charAt(0)))
k=k.substr(1)+a
c=c.substr(1)
return (c)?o+d(k,c):o}

1

Хаскелл (169)

import List
main=do c<-y;t<-y;putStrLn$map((k!!).(`mod`62))$zipWith(-)(g t)(cycle$g c)
k=['a'..'z']++['A'..'Z']++['0'..'9']
y=getLine
f(Just x)=x
g=map$f.(`elemIndex`k)

1

J: 91 символов

[:{&{.&t({&t"0&(({.t=.1|.^:(i.62)a.{~(97+i.26),(65+i.26),48+i.10)&i.)"0@:$~#)|:@(i."1.,"0)]

Например:

    g=:[:{&{.&t({&t"0&(({.t=.1|.^:(i.62)a.{~(97+i.26),(65+i.26),48+i.10)&i.)"0@:$~#)|:@(i."1.,"0)]
    'ThisIsAKey' g 'CoqKuGRUw29BiDTQmOpJFpBzlMMLiPb8alGruFbu'
ThisWorksEquallyWellWithNumbers123894576
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.