Bu ne ROT nedir? - ROT-n şifresini çöz


25

İngiliz alfabesinin harfleri sıklığa göre şöyledir:

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

Yani, een sık kullanılan mektup ve zen az kullanılanıdır. ( Vikipedi veriler .)

Buradaki zorluk, aşağıdaki gibi bazı ROT-n'd metinleri almaktır:

ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz

Bu, ROT-21 (42'nin yarısı) aracılığıyla "şifrelenmiş" olan "thisisaverysecretmessagethatisverysecureandsafe" metnidir. Yukarıdaki frekans tablosunu kullanan programınız, her bir karakterin ne kadar döndürüldüğünü ve orijinal metni belirleyebilmelidir.

(ROT-n ile ilgili bilginiz yoksa, her karakter esasen değiştirilir n. Örneğin, ROT-2'de a -> c, b -> d, ..., x -> z, y -> a, z -> b.)

Nasıl sorarsın Kullanmanız gereken (çok saf) algoritma:

  • Her biri için ngelen 0için 25kapsayıcı, ROT- uygulamak -ngiriş dizeye. (Negatif, nçünkü şifrelemeyi tersine çevirmek istiyoruz . ROT- ROT -nile eşdeğerdir 26-n, eğer daha kolaysa .)
  • Her giriş dizesini karakterlerin göreceli frekanslarını toplayarak bir sayıya dönüştürün. eolduğu 0, tolduğu 1, aolduğu 2vb Örneğin, dizi için karşılık gelen sayı "hello"7 + 0 10 + 10 + 3 = 30 ° C'dir.
  • karşılık gelen en düşük sayıya sahip olan dizeyi bulun.
  • o dizgeyi ve bunun karşılığını verir n.

Kurallar:

  • giriş makul herhangi bir yerde olabilir (STDIN, fonksiyon argümanları, bir dosyadan vb.) ve böylece çıkış (STDOUT, fonksiyon dönüş değeri, bir dosyaya vs.) gönderilebilir.
  • Her zaman aynı sonuçları ürettiği sürece farklı bir algoritma kullanabilirsiniz. Örneğin, z0 ve e25 olmak ve en yüksek sayıyı seçmek de sorun değil.
  • İki dizgede aynı puanlar varsa, ikisinden birini (veya her ikisini de) çıkarmayı seçebilirsiniz. Bu son bir durumdur ve hesaba katmanız gerekmez.
  • Bu , yani bayttaki en kısa kod kazanacak!

Test durumları:

Giriş: ocdndnvqzmtnzxmzohznnvbzocvodnqzmtnzxpmzviynvaz
Çıkış:21 thisisaverysecretmessagethatisverysecureandsafe

Giriş: pmttwxmwxtmwnxzwoziuuqvoxchhtmakwlmowtnabiksmfkpivom
Çıkış:8 hellopeopleofprogrammingpuzzlescodegolfstackexchange

Giriş: ftueimeqzodkbfqpiuftdaffiqxhqeaufygefnqbqdrqofxkemrq
Çıkış:12 thiswasencryptedwithrottwelvesoitmustbeperfectlysafe

Giriş: jgtgkuvjghkpcnvguvecugvjcvaqwowuvfgetarv
Çıkış:2 hereisthefinaltestcasethatyoumustdecrypt

Merak ediyorsanız, işte yazdığım JavaScript test kodunun bir JSFiddle'ı, attığım tüm test vakalarını başarıyla çözdü.


Son durumları not etmek faydalı olabilir. Örneğin, wtaadvermelidir 0 wtaadsonucunda ve vszzcvermelidir 25 wtaadsonucunda.
mellamokb

TrippleROT-N'nin uygulanmasını tespit etmek için ekstra puan vermelisiniz.
user19713

@ user19713 Üçlü bağlantı nedir? Yani, ROT-6 ile üç kere ROT-2 arasındaki fark nedir?
Bay Lister,

2
@mrlister, TripleDES'in çişini alan eski bir kripto şakası.
user19713

Şifrelenen dizgiden sonra n-root çıktı alabilir miyiz?
MayorMonty

Yanıtlar:


6

GolfScript - 87

Buradaki hile her dönüşü aynı anda yapmak. Her ROT sonra her karakterin üzerinde döngü yapmamız gerektiğinden, sadece her karakterin üzerinde döngü yapalım, tüm alfabeyi dilimleyin, sonra sıkıştırın. Oradan beklendiği gibi devam edin: her bir ROT için puanı sayın ve minimum olanı seçin.

Ekstra golf oynadı:

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

Sadece biraz golf oynadım:

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

Koşu

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

Uzunlukları toplamak yerine, sayıları tekdüze olarak temsil eden listeler oluşturabilirsiniz, örneğin [1,1,1,1], bu aynı sıralamayı verecektir. Daha sonra haritalama ve toplama concatMap, bir liste kavrama kullanılarak kısa sürede özeti ile yazılabilen bir hale gelir . Birkaç diğer hile ile birlikte, ben 152 karakter onu kısaltılmış: 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 karakter

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

Sonunda tekrar şifre çözme ile tekrarlama konusunda mutlu değilim, ama meh.

Ungolfed (Bu herhangi bir anlam ifade ediyorsa: P) ve biraz daha eski versiyon:

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

"giriş makul herhangi bir yerde olabilir" GolfScript yardımcı olur. İlk başta, her iki komutumuzun da neden sonda fazladan bir karakter yazdırıyor gibi göründüğünü anlayamadım 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)

Hala biraz daha golf oynayabileceğini düşünüyorum, bu yüzden önerileri hoş geldiniz!

Çözümün anlaşılmasına yardımcı olacak bazı notlar

  • m, nve oen yüksek puanı izleyin.
  • uve wkaraktere ve değer sonucuna, sırasıyla geçerlii
  • (a+a)geçmişe sarılırken taşmayı önlemeye yardımcı olur zve yapmaktan daha kısadır%26
  • Frekansı ters sırada tutuyorum, böylece min yerine max arayabilirim.

İspat: http://jsfiddle.net/J9ZyV/5/



4

C # + Linq - 273 264

Giriş dizesini alan ve kodu çözülen dizgeyi geri döndüren ve ofset'i döndüren bir işlev olarak (gereksinimlere göre):

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

Yorumsuz Ungolfed:

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
}

Küçük test sürücüsü ( System.CoreLinq için referans vermeyi derlemeyi unutmayın ):

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

Giving:

$ 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

Bence yanlış saydın - şu anki çözümün aslında 263 karakter. Ayrıca Tuple<string,int> d
aradaki

İşte uygulamada çok yakın, ancak biraz daha kısa olan 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();}
sürümüm

Bence kullanmalısın Range(0, 26), kullanmamalısın 25.
Rawling

4

dg - 137 130 129 128 bayt

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)

Örnekler:

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

Ungolfed kod:

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)

Etrafında o boşluk kaldırılamaz c - 97ve (0..26)?
14'te

Sadece ikincisini kaldırabilirim. Şimdi yapıyorum. Ben de bazı örnekler ekleyeceğim.
rubik

1
Daha dgönce hiç duymadım . Bir link verebilir misiniz?
Doktor

@TheDoctor: Tabii! pyos.github.io/dg , ana sayfadır ve öğretici pyos.github.com/dg/tutorial'dır .
rubik

97 çıkarmak yerine 7 ekleyerek bir karakter kaydedebilirsiniz. Modulo 26 bunlar aynı şeydir.
Hammar

4

J - 92 karakter

Bir parça çirkin ördek yavrusu, ama işe yarıyor. Sayıyı ve ardından dizeyi iki satırda çıktılar.

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

Aynı satırda olmalarını istiyorsanız, boşlukla ayrılmış, bu yalnızca 93 karaktere kadar çıkar , ancak daha çirkin bir rotaya gider .

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

İçin bir açıklama (/:'ctljapqhewvknfdsyigbmuoxrz'): Bu fiil, biz dize yazmak değerlerini kodlamak için vs. A = 0, B = 1, C = 2 gibi mektup değerleri üzerinde çalışacak etaoinshrdlcumwfgypbvkjxqz, en kısa yolu bunun için sıralama permütasyon almak aslında garip ip. Bunun sebebi, A'nın endeks 4, B'nin endeks 19'da, C'nin 0'da D, 14'de vb olması; bu nedenle sıralama izni, onu 4 19 0 14 8 13 ...( /:) notlandırdığınızda ve tam olarak sayı değerlerini elde ettiğinizde olur etaoin....

Kullanımı:

   (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 karakter

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

Örnek:

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

Bunu daha fazla sıkıştırmanın yolları olduğuna eminim ve diğer APL kullanıcılarını da bunun için çözümler bulmaya davet ediyorum.



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: Frekans tablosu dahil 256 karakter (okunabilirlik için yeni satırlar):

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

Metin şöyle sağlandı:

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

Ord (a) değerlerini ve uzunluğunu ölçmek isterseniz, 12 karakter atın.


1

Karaağaç - 465

Herhangi bir golf ödülü kazanmayacaksınız, ancak yazdıkça formun bir listesini görüntüleyen statik bir web sayfası oluşturuyor [(rotation number, rotated string)].

Not: henüz burada çalışmıyor, ancak resmi düzenleyiciye kopyalayıp yapıştırabilir ve çalıştırabilirsiniz.

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)]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.