이게 뭐야? -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-n'd 텍스트를 취하는 것입니다.

ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz

이 텍스트는 ROT-21 (42 분의 2)을 통해 "암호화되는" "안전하고 안전한이 보안 비밀 메시지"입니다. 위의 빈도 표를 사용하는 프로그램은 각 문자가 얼마나 회전했는지와 원본 텍스트로 결정할 수 있어야합니다.

(ROT-n에 익숙하지 않은 경우 기본적으로 각 문자를로 이동 n합니다 (예 : ROT-2, a -> c, b -> d, ..., x -> z, y -> a, z -> b)).

어떻게 물어? 사용해야하는 (매우 순진한) 알고리즘은 다음과 같습니다.

  • 각각 n025포함, 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과 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

트리 플로트 란 무엇인가? ROT-6과 ROT-2의 3 배의 차이점은 무엇입니까?
Mr Lister

2
@mrlister TripleDES에서 오줌을 꺼내는 오래된 암호 농담입니다.
user19713

해독 된 문자열 다음에 n- 루트를 출력 할 수 있습니까?
MayorMonty

답변:


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

나는 마지막에 다시 해독하여 반복에 대해 행복하지 않지만 meh.

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

자바 스크립트 (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최고 점수를 추적하십시오.
  • uw전류에 대한 각각의 문자 값과 결과를 추적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 자입니다. 또한 다음 사이의 공백을 제거하여 하나 이상의 문자를 저장할 수 있습니다.Tuple<string,int> d
mellamokb

다음은 구현에 매우 가깝지만 조금 더 짧은 내 버전입니다.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

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')

Ungolfed 코드 :

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

97을 빼는 대신 7을 추가하여 한 문자를 저장할 수 있습니다. Modulo 26은 같은 것입니다.
hammar

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에 있고, 인덱스 19에 B, 0에 C, 14에 D 등이 있기 때문입니다. 따라서 정렬 순열은 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

파이썬 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

파이썬 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.