这是什么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也是最不常用的字母。(来自Wikipedia的数据。)

您面临的挑战是获取一些ROT文本,例如:

ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz

这是通过ROT-21(42的一半)“加密”的文本“ thisisaverysecretmessageverysecureandsafe”。使用上面的频率表,您的程序应该能够确定每个字符旋转了多少以及原始文本。

(如果您不熟悉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,如果这样更容易。)
  • 通过将字符的相对频率相加,将每个输入字符串转换为数字。eis 0tis 1ais 2等。例如,字符串的相应数字为"hello"7 + 0 + 10 + 10 + 3 = 30。
  • 查找具有最低对应数字的字符串。
  • 输出该字符串及其对应的n

规则:

  • 输入可以是任何合理的位置(STDIN,函数自变量,来自文件等),因此可以输出(STDOUT,函数返回值至文件等)。
  • 您可以使用其他算法,只要它始终产生相同的结果即可。例如,具有z0和e25并选择最高的数字也是可以的。
  • 如果两个字符串的乐谱相同,则可以选择输出其中一个(或两个)。这是一个极端的情况,您无需考虑。
  • 这是,所以最短的代码(以字节为单位)将获胜!

测试用例:

输入:ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz
输出:21 thisisaverysecretmessagethatisverysecureandsafe

输入:pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom
输出:8 hellopeopleofprogrammingpuzzlescodegolfstackexchange

输入:ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq
输出:12 thiswasencryptedwithrottwelvesoitmustbeperfectlysafe

输入:jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv
输出:2 hereisthefinaltestcasethatyoumustdecrypt

如果您想知道,这里是我编写的JavaScript测试代码的JSFiddle,它成功解密了我抛出的所有测试用例。


注意边缘情况可能会很有用。例如,wtaad应该给出0 wtaad结果,并且vszzc应该给出25 wtaad结果。
mellamokb

您应该为检测TrippleROT-N的实现提供额外的分数。
user19713 2014年

@ user19713什么是Triplerot?我的意思是,ROT-6和ROT-2的三倍有什么区别?
李斯特先生,2014年

2
@mrlister这是一个古老的加密笑话,它使TripleDES摆脱了小便。
user19713 2014年

我们可以在解密的字符串之后输出n根吗?
MayorMonty '16

Answers:


6

高尔夫脚本-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]]])
hammar

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默认情况下会放置一个换行符,解释器会选择该换行符。
benchand

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,,no跟踪最高得分。
  • 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
mellamokb 2014年

这是我的版本,它的实现非常接近,但执行时间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();}

我认为您应该使用Range(0, 26)而不是25
罗林2014年

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 2014年

我只能删除第二个。现在就做。我还将添加一些示例。
rubik 2014年

1
dg以前从未听说过。您能提供一个链接吗?
TheDoctor 2014年

@TheDoctor:当然!pyos.github.io/dg是主页,pyos.github.com/dg/ tutorial 是本教程。
rubik 2014年

您可以通过加7而不是减97来保存一个字符。模26与它们是同一回事。
hammar 2014年

4

J-92字符

有点丑小鸭,但是可以用。在两行中输出数字,然后输出字符串。

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

如果您希望它们位于同一行上,并用空格隔开,则最多只能使用93个char,但采用更难看的方法。

((":@],[: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

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

不会赢得任何高尔夫奖项,但是它将创建一个静态网页,[(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)]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.