ROT này là gì? - giải mã ROT-n


25

Dưới đây là các chữ cái của bảng chữ cái tiếng Anh theo thứ tự tần số:

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

Đó là, elà chữ cái được sử dụng thường xuyên nhất, và zlà ít phổ biến nhất. (Dữ liệu từ Wikipedia .)

Thử thách của bạn là lấy một số văn bản ROT-n'd, chẳng hạn như:

ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz

Đây là văn bản "thisisaverysecretmessagethatisverysecureandsafe" được "mã hóa" thông qua ROT-21 (một nửa của 42). Chương trình của bạn, sử dụng bảng tần số ở trên, sẽ có thể xác định mức độ mỗi ký tự được xoay và văn bản gốc.

(Nếu bạn không quen thuộc với ROT-n, thì về cơ bản, nó đang dịch chuyển từng ký tự n. Ví dụ, trong ROT-2 , a -> c, b -> d, ..., x -> z, y -> a, z -> b.)

Làm thế nào, bạn hỏi? Thuật toán (rất ngây thơ) bạn phải sử dụng là:

  • cho mỗi ntừ 0để 25bao gồm, áp dụng ROT- -nvào chuỗi đầu vào. (Tiêu cực nvì chúng tôi muốn đảo ngược mã hóa. ROT- -ntương đương với ROT- 26-n, nếu điều đó dễ dàng hơn.)
  • chuyển đổi từng chuỗi đầu vào thành một số bằng cách thêm tần số tương đối của các ký tự. eis 0, tis 1, ais 2, v.v. Ví dụ, số tương ứng của chuỗi "hello"là 7 + 0 + 10 + 10 + 3 = 30.
  • tìm chuỗi có số tương ứng thấp nhất.
  • đầu ra chuỗi đó và tương ứng của nó n.

Quy tắc:

  • đầu vào có thể là bất cứ nơi nào hợp lý (STDIN, đối số chức năng, từ tệp, v.v.) và do đó có thể xuất (STDOUT, giá trị trả về của hàm, sang tệp, v.v.)
  • bạn có thể sử dụng một thuật toán khác, miễn là nó luôn tạo ra kết quả giống hệt nhau. Ví dụ, có z0 và e25 và chọn số cao nhất cũng không sao.
  • nếu hai chuỗi có điểm giống hệt nhau, bạn có thể chọn xuất một (hoặc cả hai) chuỗi đó. Đây là một trường hợp cạnh và bạn không phải tính đến nó.
  • Đây là , vì vậy mã ngắn nhất tính bằng byte sẽ giành chiến thắng!

Các trường hợp thử nghiệm:

Đầu vào: ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz
Đầu ra:21 thisisaverysecretmessagethatisverysecureandsafe

Đầu vào: pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom
Đầu ra:8 hellopeopleofprogrammingpuzzlescodegolfstackexchange

Đầu vào: ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq
Đầu ra:12 thiswasencryptedwithrottwelvesoitmustbeperfectlysafe

Đầu vào: jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv
Đầu ra:2 hereisthefinaltestcasethatyoumustdecrypt

Trong trường hợp bạn đang tự hỏi, đây là một JSFiddle về mã kiểm tra JavaScript mà tôi đã viết, nó đã giải mã thành công tất cả các trường hợp thử nghiệm mà tôi đã ném vào nó.


Nó có thể hữu ích để lưu ý các trường hợp cạnh. Ví dụ, wtaadnên đưa ra 0 wtaadnhư kết quả, và vszzcnên đưa ra 25 wtaadnhư kết quả.
mellamokb

Bạn nên cho thêm điểm để phát hiện việc triển khai TrippleROT-N.
dùng19713

@ user19713 Triplerot là gì? Ý tôi là, sự khác biệt giữa ROT-6 và ba lần ROT-2 là gì?
Ông Lister

2
@mrlister đó là một trò đùa về tiền điện tử cũ, lấy đi sự tức giận của TripleDES.
dùng19713

Chúng ta có thể xuất n-root sau chuỗi giải mã không?
MayorMonty

Câu trả lời:


6

GolfScript - 87

Gian lận ở đây là xây dựng mọi vòng quay đồng thời. Vì chúng ta cần lặp qua mỗi ROT sau đó mỗi ký tự, chúng ta chỉ cần lặp qua mỗi ký tự, cắt toàn bộ bảng chữ cái, sau đó nén nó lại. Từ đó tiến hành như mong đợi: đếm số điểm cho mỗi ROT và chọn mức tối thiểu.

Chơi gôn thêm:

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

Chỉ một chút đánh gôn:

# 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])

Đang chạy

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

Thay vì tính tổng độ dài, bạn có thể tạo các danh sách đại diện cho các số trong unary, ví dụ [1,1,1,1], và điều này sẽ đưa ra thứ tự tương tự. Ánh xạ và tổng hợp sau đó trở thành concatMapcó thể được viết ngắn gọn bằng cách sử dụng một sự hiểu biết danh sách. Kết hợp với một vài thủ thuật khác, tôi rút ngắn nó xuống còn 152 ký tự : 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 ký tự

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

Tôi không hài lòng về sự lặp lại với việc giải mã lại vào cuối, nhưng meh.

Ungolfed (nếu điều đó có ý nghĩa: P) và phiên bản cũ hơn một chút:

# 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+}%''+

"đầu vào có thể ở bất cứ đâu hợp lý" sẽ giúp GolfScript. Lúc đầu, tôi không thể hiểu tại sao cả hai tập lệnh của chúng tôi dường như in một ký tự phụ ở cuối, cho đến khi tôi nhận ra echođặt một dòng mới theo mặc định, mà trình thông dịch chọn.
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)

Tôi nghĩ rằng nó vẫn có thể được chơi golf nhiều hơn một chút, vì vậy đề xuất hoan nghênh!

Một số lưu ý giúp hiểu giải pháp

  • m, notheo dõi số điểm cao nhất.
  • uwtheo dõi kết quả của ký tự và giá trị, tương ứng cho hiện tạii
  • (a+a)giúp ngăn ngừa tràn khi quấn quanh quá khứ zvà ngắn hơn so với thực hiện%26
  • Tôi có tần số theo thứ tự ngược lại để tôi có thể tìm kiếm tối đa thay vì tối thiểu.

Bằng chứng: http://jsfiddle.net/J9ZyV/5/



4

C # + Linq - 273 264

Là một hàm lấy chuỗi đầu vào và trả về chuỗi được giải mã & offset (theo yêu cầu):

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);}

Ungolfed với ý kiến:

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
}

Trình điều khiển thử nghiệm nhỏ (nhớ biên dịch tham chiếu System.Corecho 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));
            }
        }
    }
}

Tặng:

$ 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

Tôi nghĩ rằng bạn đã nhầm lẫn - giải pháp hiện tại của bạn thực sự là 263 ký tự. Ngoài ra, bạn có thể lưu thêm một char bằng cách xóa khoảng Tuple<string,int> d
trắng

Đây là phiên bản của tôi rất gần trong triển khai nhưng ngắn hơn một chút: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 23/03 '

Tôi nghĩ bạn nên sử dụng Range(0, 26), không 25.
Rawling

4

dg - 137 130 129 128 byte

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)

Ví dụ:

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

Mã bị đánh cắp:

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)

Bạn không thể loại bỏ những không gian xung quanh c - 97(0..26)?
mniip

Tôi chỉ có thể loại bỏ cái thứ hai. Làm nó bây giờ. Tôi cũng sẽ thêm một số ví dụ.
rubik

1
Chưa bao giờ nghe nói dgtrước đây. bạn có thể cung cấp một liên kết?
TheDoctor

@TheDoctor: Chắc chắn rồi! pyos.github.io/dg là trang chủ và pyos.github.com/dg/tutorial hướng dẫn.
rubik

Bạn có thể lưu một ký tự bằng cách thêm 7 thay vì trừ 97. Modulo 26 chúng giống nhau.
hammar

4

J - 92 char

Một chút vịt con xấu xí, nhưng nó hoạt động. Xuất ra số và sau đó là chuỗi, trên hai dòng.

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

Nếu bạn muốn chúng nằm trên cùng một đường, phân tách không gian, thì điều này chỉ lên tới 93 char , nhưng có một tuyến đường xấu hơn.

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

Giải thích cho (/:'ctljapqhewvknfdsyigbmuoxrz'): Trong động từ này, chúng tôi hoạt động dựa trên các giá trị chữ cái là A = 0, B = 1, C = 2, v.v. Để mã hóa các giá trị chữ cái của chuỗi etaoinshrdlcumwfgypbvkjxqz, cách ngắn nhất thực sự là hoán vị sắp xếp cho điều này chuỗi lạ. Điều này là do A ở chỉ số 4, B ở chỉ số 19, C ở 0, D ở 14, v.v. do đó hoán vị sắp xếp là 4 19 0 14 8 13 ...khi bạn chấm điểm ( /:) nó và bạn nhận được chính xác các giá trị số cho etaoin....

Sử dụng:

   (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 ký tự

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

Thí dụ:

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

Tôi chắc chắn có nhiều cách để nén điều này hơn nữa và tôi mời bất kỳ người dùng APL nào khác đưa ra giải pháp cho điều đó.


6
Bạn cũng phải xuất chuỗi quyết định ...
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 char (cộng với dòng mới cho khả năng đọc) bao gồm bảng tần số:

@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;

Văn bản được cung cấp như vậy:

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

Tắt 12 char nếu bạn muốn tìm hiểu các giá trị của ord (a) và độ dài của @f


1

Cây cối - 465

Sẽ không giành được bất kỳ giải thưởng golf nào, nhưng nó tạo ra một trang web tĩnh hiển thị danh sách các hình thức [(rotation number, rotated string)]khi bạn nhập.

Lưu ý: chưa hoạt động ở đây nhưng bạn có thể sao chép-dán nó vào trình chỉnh sửa chính thức và chạy nó.

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

Con trăn 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)]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.