これは何の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

これは、ROT-21(42の半分)を介して「暗号化」されたテキスト「thisisaverysecretmessage thatvery secure and safe」です。プログラムは、上記の頻度表を使用して、各文字がどれだけ回転したかと元のテキストによって判断できるはずです。

(ROT-nに慣れていない場合は、基本的に各文字をn。でシフトします。たとえば、ROT-2では、a -> c, b -> d, ..., x -> z, y -> a, z -> b。)

どうして?使用する必要がある(非常に単純な)アルゴリズムは次のとおりです。

  • nfromから0to 25までのそれぞれについて、ROT- -nを入力文字列に適用します。(暗号化nにしたいため、負の値になります。ROT- -nはROT- と同等26-nです。
  • 文字の相対頻度を合計することにより、各入力文字列を数値に変換します。eis 0tis 1ais 2など。たとえば、文字列に対応する番号"hello"は7 + 0 + 10 + 10 + 3 = 30です。
  • 対応する最小の番号を持つ文字列を見つけます。
  • その文字列とそれに対応するn

ルール:

  • 入力はどこでも合理的(STDIN、関数の引数、ファイルからなど)であり、出力(STDOUT、関数の戻り値、ファイルなど)でもかまいません。
  • 常に同じ結果が得られる限り、異なるアルゴリズムを使用できます。たとえば、z0 eで25であっても、最大数を選択しても問題ありません。
  • 2つの文字列のスコアが同じ場合、どちらか(または両方)を出力することを選択できます。これはエッジケースであり、説明する必要はありません。
  • これはなので、バイト単位の最短コードが勝ちます!

テストケース:

入力:ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz
出力:21 thisisaverysecretmessagethatisverysecureandsafe

入力:pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom
出力:8 hellopeopleofprogrammingpuzzlescodegolfstackexchange

入力:ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq
出力:12 thiswasencryptedwithrottwelvesoitmustbeperfectlysafe

入力:jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv
出力:2 hereisthefinaltestcasethatyoumustdecrypt

あなたは不思議に思った場合は、ここで成功した私はそれで投げたすべてのテストケースを復号化し、私が書いたJavaScriptのテストコードのJSFiddleは、あります。


エッジケースに注意することが役立つ場合があります。たとえば、wtaad与える必要があり0 wtaad、結果として、そしてvszzc与える必要があり25 wtaad、結果として。
mellamokb 14年

TrippleROT-Nの実装を検出するには、追加のポイントを与える必要があります。
user19713 14年

@ user19713 triplerotとは何ですか?つまり、ROT-6と3倍のROT-2の違いは何ですか?
ミスターリスター14年

2
@mrlisterは、TripleDESから小便を取り出す古い暗号のジョークです。
user19713

解読された文字列の後にn-rootを出力できますか?
MayorMonty

回答:


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

ハスケル- 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 14年

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)

まだもう少しゴルフできると思うので、提案を歓迎します!

ソリューションを理解するのに役立つ注意事項

  • mno最高のスコアを追跡します。
  • 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.CoreLinqの参照をコンパイルすることを忘れないでください):

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文字です。また、次の文字の間のスペースを削除することにより、もう1つの文字を保存できます。Tuple<string,int> d
mellamokb 14年

実装は非常に近いが、少し短い私のバージョンを次に示します。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();}
14年

Range(0, 26)ではなく、使うべきだと思います25
ローリング14年

4

DG - 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 14年

削除できるのは2番目だけです。今それをしています。いくつかの例を追加します。
ルービック

1
dg前に聞いたことがない。リンクを提供してもらえますか?
TheDoctor

@TheDoctor:もちろん!pyos.github.io/dgはホームページで、pyos.github.com / dg / tutorialはチュートリアルです。
ルービック

97を減算する代わりに7を追加することで、1文字を保存できます。モジュロ26は同じものです。
ハンマー14年

4

J-92文字

少しいアヒルの子ですが、動作します。数値を出力してから文字列を2行で出力します。

(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
決定した文字列も出力する必要があります...
Doorknob

2

Python 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

ord(a)の値と@fの長さをベイクインする場合は、12文字を外します


1

ニレ-465

ゴルフ賞を獲得するつもりはありませんが、入力するとフォームのリストを表示する静的なWebページが作成さ[(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

Python 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)]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.