Що це за ROT? - розшифрувати ROT-n


25

Ось літери англійського алфавіту впорядковані за частотою:

e t a o i n s h r d l c u m w f g y p b v k j x q z

Тобто, eце найчастіше вживаний лист і zє найменш поширеним. (Дані з Вікіпедії .)

Ваше завдання полягає в тому, щоб взяти текст ROT-n'd, наприклад:

ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz

Це текст "thisisaverysecretmessagethatisverysecureandsafe", який "шифрується" через ROT-21 (половина з 42). Ваша програма, використовуючи вищевказану таблицю частот, повинна мати можливість визначати, наскільки обертається кожен символ та початковий текст.

(Якщо ви не знайомі з ROT-n, він по суті зміщує кожен символ на n. Наприклад, в ROT-2,. a -> c, b -> d, ..., x -> z, y -> a, z -> b)

Як, запитаєте ви? (Дуже наївний) алгоритм, який ви повинні використовувати:

  • для кожного nз 0до 25включно, застосовуються ROT- -nдо вхідному рядку. (Негативно, nтому що ми хочемо змінити шифрування. ROT- -nеквівалентно ROT- 26-n, якщо це простіше.)
  • перетворити кожен рядок введення в число, додавши відносні частоти символів. eє 0, tє 1, aє 2і т. п. Наприклад, відповідне число для рядка "hello"дорівнює 7 + 0 + 10 + 10 + 3 = 30.
  • знайдіть рядок, який має найменше відповідне число.
  • виведіть цей рядок та його відповідні n.

Правила:

  • введення може бути де завгодно розумним (STDIN, аргументи функції, з файлу тощо), і так може виводити (STDOUT, значення повернення функції, у файл тощо)
  • ви можете використовувати інший алгоритм, якщо він завжди дає однакові результати. Наприклад, мати z0 і eбути 25 і вибрати найбільше число також нормально.
  • якщо два рядки мають однакові бали, ви можете вивести один (або обидва) з них. Це кращий випадок, і вам не доведеться це враховувати.
  • це , тому найкоротший код у байтах виграє!

Тестові приклади:

Вхід: ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz
Вихід:21 thisisaverysecretmessagethatisverysecureandsafe

Вхід: pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom
Вихід:8 hellopeopleofprogrammingpuzzlescodegolfstackexchange

Вхід: ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq
Вихід:12 thiswasencryptedwithrottwelvesoitmustbeperfectlysafe

Вхід: jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv
Вихід:2 hereisthefinaltestcasethatyoumustdecrypt

Якщо вам було цікаво, ось JSFiddle тестового коду JavaScript, який я успішно розшифрував усі тестові випадки, які я накинув на нього.


Можливо, буде корисно відзначити крайові випадки. Наприклад, wtaadслід дати 0 wtaadяк результат, а vszzcтакож дати 25 wtaadяк результат.
mellamokb

Вам слід надати додаткові бали за виявлення реалізації TrippleROT-N.
користувач19713

@ user19713 Що таке триплеро? Я маю на увазі, яка різниця між ROT-6 і трьома разів ROT-2?
Містер Лістер

2
@mrlister - це стара жарта криптовалюта, яка виводить з себе мотивацію TripleDES.
user19713

Чи можемо ми вивести n-root після розшифрованого рядка?
МерМонті

Відповіді:


6

GolfScript - 87

Обман тут полягає в тому, щоб будувати кожне обертання одночасно. Оскільки нам потрібно перевести цикл на кожну ROT, то кожен символ, давайте просто перевернемо кожен символ, нарізаємо весь алфавіт, а потім зашпаркуємо його. Звідти продовжуйте, як очікувалося: підраховуйте бал за кожну ROT і вибирайте мінімум.

Додатковий гольф:

{97- 26,{97+}%.+''+>}/]{27<}%zip:d{{"etaoinshrdlcumwfgypbvkjxqz"?}%{+}*}%.$0=?.26\-\d=

Лише трохи гольфу:

# the alphabet, and by frequency
26,{97+}%.+''+:a;
"etaoinshrdlcumwfgypbvkjxqz":f;

# build evey ROT decryption
{97-a>}/]{27<}%zip:d

# calculate likelihood
{{f?}%{+}*}%.

# find min
$0=

# output rotation factor and decryption
?.26\-\d=

8

Haskell - 192 175

f y=sum.map(\x->length.fst$break(==x)y)
main=interact(\s->snd$minimum$[(f"etaoinshrdlcumwfgypbvkjxqz"r,show(26-n)++" "++r)|n<-[0..25],let r=map(\x->([x..'z']++['a'..])!!n)s])

Біг

% ./rot-n <<< "pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom"
8 hellopeopleofprogrammingpuzzlescodegolfstackexchange

Замість того, щоб підсумовувати довжини, ви можете сформувати списки, що представляють числа унарних, наприклад [1,1,1,1], і це дасть те саме впорядкування. Потім відбувається картографування та підбиття підсумків, concatMapяке можна записати лаконічно, використовуючи розуміння списку. У поєднанні з деякими іншими трюками, я вкоротив до 152 символів: main=interact(\s->snd$minimum[([1|x<-r,_<-fst$span(/=x)"etaoinshrdlcumwfgypbvkjxqz"],show(26-n)++' ':r)|n<-[0..25],r<-[[([x..'z']++['a'..])!!n|x<-s]]]).
Хаммар

7

GolfScript, 112 108 102 100 символів

{{}/]{97-}%}:b~:|;"etaoinshrdlcumwfgypbvkjxqz"b:f,:&,{:x[|{&x-+&%f?}%{+}*\]}%$0=1=:x|{&x-+&%97+}%''+

Мені не подобається повторення з повторним розшифруванням в кінці, але мех.

Ungolfed (якщо це має сенс: P) та трохи старша версія:

# store input IDs (a = 0, b = 1, etc.) in s
[{}/]{97-}%:s;
# store frequency data IDs in f (blah, repetition)
"etaoinshrdlcumwfgypbvkjxqz"[{}/]{97-}%:f

# for each number from 0 to 26 (length of previous string left unpopped)...
,,{
  # the number is x
  :x;
  # return an array of...
  [
    # the score
    s{x 26\-+26%f?}%{+}*
    # and the n
    x
  ]
}%

# use $ort to find the n to output
$0=1=:x

# get the string that the n corresponded to (blah, more repetition)
s{x 26\-+26%97+}%''+

"введення може бути де завгодно розумним" допомагає GolfScript. Спочатку я не міг зрозуміти, чому, здавалося, обидва наші сценарії друкують зайвий символ наприкінці, поки я не зрозумів, echoщо за замовчуванням ставиться новий рядок, який підбирає інтерпретатор.
couchand

6

JavaScript (205)

f='zqxjkvbpygfwmucldrhsnioate';a='abcdefghijklmnopqrstuvwxyz';for(s=prompt(o=m=n=0)
,i=27;i--;w>m&&(m=w,n=i,o=u))for(u='',w=c=0;c<s.length;w+=f.indexOf(x))u+=x=(a+a)[a
.indexOf(s[c++])+i];alert((26-n)+' '+o)

Я думаю, що все-таки можна пограти трохи більше, тому пропозиції ласкаво просимо!

Деякі нотатки, які допоможуть зрозуміти рішення

  • m, nі oвідстежуйте найвищий бал.
  • uі wвідслідковувати характер і значення результату відповідно для поточногоi
  • (a+a)допомагає запобігти переповненню під час обгортання минулого zі коротший, ніж при виконанні%26
  • У мене частота в зворотному порядку, тому я можу шукати макс замість хв.

Доказ: http://jsfiddle.net/J9ZyV/5/



4

C # + Linq - 273 264

Як функція, яка приймає рядок введення і повертає декодований рядок і зміщення (відповідно до вимог):

static Tuple<string,int> d(string s){var r=Enumerable.Range(0,25).Select(i=>string.Concat(from c in s select (char)((c-97+i)%26+97))).OrderBy(x=>(from c in x select "etaoinshrdlcumwfgypbvkjxqz".IndexOf(c)).Sum()).First();return Tuple.Create(r,(s[0]-r[0]+26)%26);}

Безголовка з коментарями:

static Tuple<string,int> d(string s)
{
    var r=Enumerable.Range(0,25)                                               // for every possible offset i
          .Select(i=>string.Concat(from c in s select (char)((c-97+i)%26+97))) // calculate rot_i(input string)
          .OrderBy(                                                            // order these by their score
              x=>(
              from c in x select "etaoinshrdlcumwfgypbvkjxqz".IndexOf(c)       // lookup frequency of each character
              ).Sum()                                                          // and sum each frequency to get the score
           ).First();                                                          // get the first one (lowest score)

    return Tuple.Create(r,(s[0]-r[0]+26)%26);                                  // compute offset and return results
}

Маленький тестовий драйвер (не забудьте скласти посилання System.Coreна Linq):

using System;
using System.Linq;

namespace codegolf
{
    class Program
    {
        static Tuple<string,int> d(string s){var r=Enumerable.Range(0,25).Select(i=>string.Concat(from c in s select (char)((c-97+i)%26+97))).OrderBy(x=>(from c in x select "etaoinshrdlcumwfgypbvkjxqz".IndexOf(c)).Sum()).First();return Tuple.Create(r,(s[0]-r[0]+26)%26);}

        static void Main(string[] args)
        {
            while (true)
            {
                var input = Console.ReadLine();
                if (input == null) break;
                var retval = d(input);
                Console.WriteLine(String.Format("{0} {1}", retval.Item2, retval.Item1));
            }
        }
    }
}

Давання:

$ mcs /reference:System.Core.dll main.cs && mono ./main.exe
ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz
21 thisisaverysecretmessagethatisverysecureandsafe
pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom
8 hellopeopleofprogrammingpuzzlescodegolfstackexchange
ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq
12 thiswasencryptedwithrottwelvesoitmustbeperfectlysafe
jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv
2 hereisthefinaltestcasethatyoumustdecrypt
thisisaverysecretmessagethatisverysecureandsafe
0 thisisaverysecretmessagethatisverysecureandsafe

Я думаю, що ви зробили неправильний рахунок - ваше поточне рішення насправді 263 символи. Також ви можете зберегти ще одну Tuple<string,int> d
таблицю,

Ось моя версія, яка дуже близька до реалізації, але трохи коротша:Tuple<int,string>f(string x){return Enumerable.Range(0,25).Select(n=>Tuple.Create(26-n,string.Concat(x.Select(c=>(char)((c-97+n)%26+97))))).OrderBy(t=>(t.Item2.Select(c=>"etaoinshrdlcumwfgypbvkjxqz".IndexOf(c))).Sum()).First();}
porges

Я думаю, ви повинні використовувати Range(0, 26), ні 25.
Роулінг

4

дг - 137 130 129 128 байт

f=t->min key:(t->sum$map 'etaoinshrdlcumwfgypbvkjxqz'.index$snd t)$map(n->n,''.join$map(c->chr$((ord c + 7-n)%26+ 97))t)(0..26)

Приклади:

>>> f 'ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz'
(21, 'thisisaverysecretmessagethatisverysecureandsafe')
>>> f 'pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom'
(8, 'hellopeopleofprogrammingpuzzlescodegolfstackexchange')
>>> f 'ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq'
(12, 'thiswasencryptedwithrottwelvesoitmustbeperfectlysafe')
>>> f 'jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv'
(2, 'hereisthefinaltestcasethatyoumustdecrypt')

Невикористаний код:

func = t ->
  #: Compute the score of the text `t` with respect to the frequency table.
  #: score :: (int, str) -> int
  score = t ->
    sum $ map 'etaoinshrdlcumwfgypbvkjxqz'.index $ snd t

  #: Compute rot-n of the string `t`. Return the offset and the shifted text.
  #: rot :: int -> (int, str)
  rot = n ->
    n, ''.join $ map (c->chr $ ((ord c + 7 - n) % 26 + 97)) t

  # return the minimum (computed by `score`) amongst all shifted messages
  min key: score $ map rot (0..26)

Ви не можете видалити ці простори навколо c - 97та (0..26)?
mniip

Я можу видалити лише другий. Робити це зараз. Я також додам кілька прикладів.
rubik

1
Ніколи dgраніше не чув . Не могли б ви надати посилання?
TheDoctor

@TheDoctor: Звичайно! pyos.github.io/dg - це домашня сторінка, а навчальний посібник pyos.github.com/dg/tutorial .
rubik

Ви можете зберегти один символ, додавши 7, а не віднімаючи 97. Modulo 26 - це те саме.
хаммар

4

J - 92 char

Трохи потворного каченя, але це працює. Виводить число, а потім рядок у двох рядках.

(26|](-1!:2&2&.":)(/:'ctljapqhewvknfdsyigbmuoxrz')+/@i."1(i.<./@:)26|(i.-27)+/])&.(_97+3&u:)

Якщо ви хочете, щоб вони знаходилися на одній лінії, простір розділений, це лише до 93 знаків , але займає більш неприємний шлях.

((":@],[:u:32,97+26|-)(/:'ctljapqhewvknfdsyigbmuoxrz')+/@i."1(i.<./@:)26|(i.-27)+/])@(7+3&u:)

Пояснення (/:'ctljapqhewvknfdsyigbmuoxrz'): У цьому дієслові ми працюємо над значеннями літери як A = 0, B = 1, C = 2 і т. Д. Для кодування буквених значень рядка etaoinshrdlcumwfgypbvkjxqzнайкоротшим способом є власне прийняття перестановки сортування для цього дивна струна. Це тому, що A знаходиться в індексі 4, B в індексі 19, C в 0, D в 14 і так далі; отже, перестановка сортування - це 4 19 0 14 8 13 ...коли ви оцінюєте її ( /:), і ви отримуєте саме значення числа etaoin....

Використання:

   (26|](-1!:2&2&.":)(/:'ctljapqhewvknfdsyigbmuoxrz')+/@i."1(i.<./@:)26|(i.-27)+/])&.(_97+3&u:) 'ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz'
21
thisisaverysecretmessagethatisverysecureandsafe

   NB. naming for convenience
   f =: (26|](-1!:2&2&.":)(/:'ctljapqhewvknfdsyigbmuoxrz')+/@i."1(i.<./@:)26|(i.-27)+/])&.(_97+3&u:)
   f 'pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom'
8
hellopeopleofprogrammingpuzzlescodegolfstackexchange
   f 'wtaad'
0
wtaad

3

q, 97

{(w;m w:g?min g:(+/')("etaoinshrdlcumwfgypbvkjxqz"!t)m:(t!u!/:rotate[;u:.Q.a]'[(-)t:(!)26])@\:x)}

.

q) tests:(
    "ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvazocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz";
    "pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom";
    "ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq";
    "jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv")

q) f:{(w;m w:g?min g:(+/')("etaoinshrdlcumwfgypbvkjxqz"!t)m:(t!u!/:rotate[;u:.Q.a]'[(-)t:(!)26])@\:x)}

q) f each tests
21 "thisisaverysecretmessagethatisverysecureandsafethisisaverysecretmessagethatisverysecureandsafe"
8  "hellopeopleofprogrammingpuzzlescodegolfstackexchange"
12 "thiswasencryptedwithrottwelvesoitmustbeperfectlysafe"
2  "hereisthefinaltestcasethatyoumustdecrypt"

2

APL - 70 символів

F←{↑⍋+/'etaoinshrdlcumwfgypbvkjxqz'⍳⊃(⍳26){l[(⍺⌽l←⎕UCS 97+⍳26)⍳⍵]}¨⊂⍵}

Приклад:

      F 'ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz'
21
      F 'pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom'
8
      F 'ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq'
12
      F 'jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv'
2

Я впевнений, що існують способи подальшого стиснення цього питання, і я запрошую будь-яких інших користувачів APL розглянути рішення для цього.


6
Ви також маєте вивести вирішений рядок ...
Дверна ручка

2

Пітон 188

x="abcdefghijklmnopqrstuvwxyz"
y=input()
r=lambda n:"".join(x[x.find(i)-n]for i in y)
s={sum("etaoinshrdlcumwfgypbvkjxqz".find(b)for b in r(a)):(a,r(a))for a in range(26)}
print(s[min(s)])

1

Perl: 256 знаків (плюс нові рядки для читабельності), включаючи таблицю частот:

@f=unpack("W*","etaoinshrdlcumwfgypbvkjxqz");
@c=unpack("W*",<>);$m=ord("a");$b=1E10;
for$n(0..25){$s=0;$t="";
for$x(0..scalar@c){$r=($c[$x]-$n-$m)%26+$m;$t.=chr($r);
for(0..scalar@f){if($r==$f[$_]){$s+=$_}}}
if($s<$b){$b=$s;$w=$t;$a=$n}}
printf"%d %s\n",$a,$w;

Текст надається так:

echo "ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz" | perl ./freq.pl 
21 thisisaverysecretmessagethatisverysecureandsafewm

Зніміть 12 знаків, якщо ви хочете вписати значення ord (a) та довжину @f


1

В'яз - 465

Не збирається вигравати жодної нагороди за гольф, але це робить статичну веб-сторінку, яка відображає список форми [(rotation number, rotated string)]під час введення.

Примітка: тут ще не працює, але ви можете скопіювати і вставити його в офіційний редактор і запустити його.

import String as S
import Char (..)
import Graphics.Input (..)
import Graphics.Input.Field (..)
f="ETAOINSHRDLCUMWFGYPBVKJXQZ"
r s n=let t c=mod(toCode c-65+n)26+65 in map(fromCode . t)(S.toList s)
w s=case s of 
 ""->0
 s->sum(S.indexes(S.left 1 s)f)+w(S.dropLeft 1 s)
b s=sort<|map(\x->((w . S.fromList . r s)x,(26-x,S.fromList<|r s x)))[0..25]
c=input noContent
main=above<~(field defaultStyle c.handle id""<~c.signal)~(asText . b . .string<~c.signal)

1

Пітон 2, 171

f,R,i='zqxjkvbpygfwmucldrhsnioate',{},raw_input();a=sorted(f)*2
for n in range(26):_=''.join(a[ord(x)-71-n]for x in i);R[sum(2**f.index(x)for x in _)]=n,_
print R[max(R)]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.