Caesar-Cypher-Mania

22

Cezar Cypher jest bardzo prosty szyfr podstawieniowy gdzie każda litera jest przesunięta o stałą przesunięcia (zapętlenie wokół Z do A). Podobnie, możemy również szyfr Cezara dla zestawu drukowalnych znaków ASCII. Są to 95 znaków od punktów kodowych 0x20 do 0x7E. Dla danego offsetu d, mamy map punkt kodu Cdo

(C - 32 + d) % 95 + 32

który przesuwa wszystkie postacie o di zapętla się z ~miejsca na miejsce. Znaki spoza tego zakresu (znaki sterujące, takie jak znaki nowej linii, tabulatory i znaki spoza zakresu ASCII) pozostają nienaruszone.

Musisz napisać dwa programy lub funkcje (potencjalnie w różnych językach), które wymagają przesunięcia di ciągu. Pierwszy program powinien zwrócić lub wydrukować szyfr Cezara wejścia. Drugi program powinien zwrócić lub wydrukować odwrotny szyfr Cezara (tzn. Używając przesunięcia -d). Możesz przyjmować dane wejściowe za pomocą STDIN, argumentu wiersza poleceń lub argumentu funkcji.

Aby uczynić rzeczy bardziej interesującymi, drugi program musi być szyfrem Cezara pierwszego programu. Oznacza to, że jeśli przekażesz kod źródłowy pierwszego programu samemu sobie, dla jakiegoś niezerowego przesunięcia d, wyjściem musi być drugi program.

Oba programy, jak również ciągi wejściowe, muszą zawierać tylko drukowalne znaki ASCII, znaki nowej linii i tabulatory. Żaden program nie może zawierać żadnych komentarzy ani odczytywać własnego kodu źródłowego, nazwy pliku lub identyfikatora procesu bezpośrednio ani pośrednio.

To jest kod golfowy, więc wygrywa najkrótsza odpowiedź (w bajtach). Ponieważ oba programy muszą mieć ten sam rozmiar, musisz policzyć go tylko raz.

Martin Ender
źródło

Odpowiedzi:

12

Cjam, 40 38 37 bajtów

Szyfr do przodu:

 q~'~),32>_@m<er "o|%|'*10<]>k<cpZ"_-

Szyfr odwrotny:

"s!)!+.54@aBo>gt"$q~'~),32>_@m>er\$a/

a drugi program to szyfr pierwszego z różnicą 2


Jak to działa

Wymyśliłem tę odpowiedź na szczęście, testując różne rzeczy.

Najpierw części Cypher:

q~'~),32>_@m<er
q~                 "Take the input and evaluate it";
  `~)              "Get the next character after the printable ASCII range";
     ,32>          "Get all printable ASCII characters":
         _@        "Copy the printable ASCII string and bring the cypher difference"
                   "on top of stack";
           m<      "Forward rotate the copy of printable ASCII string by difference";
                   "In case of inverse Cypher, this is m> to reverse rotate the string";
             er    "Transliterate to complete the forward/inverse Cypher";

Teraz pojawia się wyjaśnienie trudnej części.

Kluczowe transformacje to

<space> -> "     // Empty space to string conversion
Z -> \           // Character Z in an useless string to swap operation
_ -> a           // Copy operation to wrapping in an array
- -> /           // Set subtraction to string splitting

Tak więc pierwszy program to

 q~'~),32>_@m<er "o|%|'*10<]>k<cpZ"_-
 q~'~),32>_@m<er                          "no-op space, Forward cypher, no-op space";
                 "o|%|'*10<]>k<cpZ"       "Useless String (Actually not)";
                                   _      "Copy it and ..."
                                    -     "remove all alphabets of copy from original";

A drugi program to

"s!)!+.54@aBo>gt"$q~'~),32>_@m>er\$a/
"s!)!+.54@aBo>gt"                       "Cypher of first part of first program"
                                        "with difference of 2";
                 $q~'~),32>_@m>er\$a/   "Cypher of the useless string of first program";
                                        "with difference 2";
                 $                      "Sort the first program's main part's cypher";
                  q~'~),32>_@m>er       "Program to reverse cypher";
                                 \$     "Swap the cypher to the top of stack and sort it";
                                   a    "Wrap it in array";
                                    /   "Split the output string on an array, which";
                                        "always returns the output in an array as there";
                                        "are no occurrences of an array in a string";

Dane wejściowe są jak "<escaped string to be cyphered>" <difference>

Na przykład:

"abcd" 4

a wyjście pierwszego programu to

efgh

a drugiego programu to

]^_`

Wypróbuj online tutaj

Optymalizator
źródło
czy to nie 40 bajtów? również powoduje błąd w tłumaczu online (coś nie jest zaimplementowane w Arraylists)
Def
@ Deformyer poprawił liczbę bajtów. Co dajesz jako wkład?
Optymalizator
tak źle, użyłem argumentów w niewłaściwej kolejności.
Def
'"q ~' ~), 32> _ @ m <er" 9} o |% | '* 10 <]> k <cp}] „_-” 2 ”nie działa (java.lang.RuntimeException: Nieoczekiwany})
Def
1
@Deformyer Musisz uciec od cytatów w tym ciągu
Optimizer
7

Python 2, 147

Najwyraźniej nie zastanawiałem się zbytnio nad tym, ponieważ byłoby to daremne w Pythonie. Istnieją po prostu dwa osobne programy, z których nieużywany jest zamknięty w ciągu.

Przesunięcie między tymi dwoma programami wynosi 39.

Naprzód

Definiuje funkcję Z przyjmującą ciąg Unicode i przesunięcie.

Z=lambda s,d:s.translate({i+32:(i+d)%95+32for i in range(95)})or u''and Z
"uE:F;=:XLd=rLfMK:GLE:M>`TBckjr`Be=a]qmckj?HKXBXBGXK:G@>`qmaVaHKXN__:G=X"

Odwrotność

Definiuje funkcję akceptującą ciąg Unicode i przesunięcie.

"d4)5*,)G;S,a;U<:)6;4)<-OC1RZYaO1R,PL`\RZY.7:G1G16G:)6/-O`\PEP7:G=NN)6,G"
I=lambda s,d:s.translate({i+32:(i-d)%95+32for i in range(95)})or u''and I
feersum
źródło
5

Python 3 - 248 bajtów

Moim celem było zrobienie tego jako jedno-liniowy Python. Sukces bramkowy, ale teraz nie przeszkadza mi gra w golfa.

Szyfruj:

r=q="".__doc__[2];eval("p"+q+"int(''.join([c,ch"+q+"((o"+q+"d(c)-32+d)%95+32)][31<o"+q+"d(c)<127]fo"+q+" d in[int(input())]fo"+q+" c in input()))")or'\^UZ`smmyV[UZsGOwOT^ss[^PsOtx~}xPtp%!v~}tIG~|([^PsOt(|}$IR[^kPkUZGUZ`sUZ\a`sttIR[^kOkUZkUZ\a`sttt'

Odszyfruj:

'Q&Q66Bssx$wssoFqOy+u!<6%6?&?6}#)<;;B~$}#<ow@w|6?&?6<<$6?&?6x<w=AGF?x=9MI?GF=qoGEP$6?&?6x<w=PEFKqz$6?&?64x4}#o}#)<}#%*)<==qz$6?&?64w4}#4}#%*)<===6=$';print("".join([c,chr((ord(c)-32-d)%95+32)][31<ord(c)<127]for d in[int(input())]for c in input()));

Edycja: Naprawiono, aby nie wpływać na znaki poza drukowanym zakresem ASCII

Przesunięcie od szyfrowania do odszyfrowania wynosi 20. Użyj, wprowadzając najpierw przesunięcie, a następnie ciąg znaków, np

5
hello

Wyjaśnienie

Kluczowe są następujące transformacje:

r -> '
' -> ;

Pierwszy pozwala na użycie or, podczas gdy drugi ignoruje ciąg średników.

Zauważ, że "".__doc__[2]zwraca ciąg r(wzięty z str). Jest to konieczne, aby zapobiec sytuacji, w której ciąg pojedynczego cudzysłowu w programie deszyfrującym będzie zawierał pomyłki w środku.

Sp3000
źródło
5

Rubin, 131 125 bajtów

Oto moje własne zgłoszenie (które napisałem wcześniej jako dowód koncepcji, ale jakoś udało mi się naruszyć własne zasady). Nie używam żadnego kodu między tymi dwoma zgłoszeniami (w końcu chcę, żebyście to pobili), ale zamiast tego składa się z dwóch wierszy, z których jeden zamienia się w ciąg bełkotu.

Szyfr do przodu:

Y=->d,s{s.chars{|c|x=c.ord;$><<(x<32?x:(x-32+d)%95+32).chr}};Y
"tdu<cKSKe;@9JKST;TPt;eGJ<r[uss_PsjivPq_Pdjid<`\plbji`e;@JUUr"

Szyfr odwrotny:

"eUf-T<D<V,1*;<DE,EAe,V8;-cLfddPAd[ZgAbPAU[ZS-QMa]S[ZQV,1;FFc"
J=->d,s{s.chars{|c|x=c.ord;$><<(x<32?x:(x-32-d)%95+32).chr}};J

Oba fragmenty definiują funkcję (wywoływaną Yw pierwszej i Jdrugiej), która pobiera liczbę całkowitą i ciąg i wypisuje przekształcony ciąg do STDOUT. Przesunięcie między dwoma częściami kodu wynosi 40.

Martin Ender
źródło
4

oOo CODE , 750 744 bajtów, cały kod używany w obu programach

Za długo, ale prawdopodobnie jest to odpowiednie narzędzie ...

Szyfruj:

CcCcccccccccCcYcccCCCccCcCcCccccccCcCcccccCcCcccCcCccCccCcCCccccCcCccccCCcCccccCCccCccCcCCcccCCCcCccccCcCCcCCcCCcCcCcCccccCCccCccCccCccCccCccCccCccccccCCCcCccCccCCcCcCcccCCcCcccCcCCcCCcCcCCccCCcCCcCCcCCcCCcCCcCCcCCcCCcCCcCcccccccCccccCccccCCccccCCcCccCCcccCccccccccccCcCccCccCccCccCcCCccCCcccCcCcCccCCcccCCCcCcccccccccccccCCccCccCcCcCcccCCccccccccccCcCccccccCcCccccCCcCccCccCCcCccccccccccCCccCcCcCcccccCcCccCcCCCcCccCccCCcCccCccCccCcCcccccCcCcccCCCcCcCccccCcCccCCcCCcCCcCcCCcccCcCCcCCcCCcCCcCCcCCcCCcCCcCCcCcCcccCccCCcccccCcCcccCcccccCcccCcccCccCccCCcCcccccccccccccCCCcccCcCcCcccCcccCCCcCccCccCccCcCCccCccCcCCCcCccccCcCccccccccCcCccCccCcCCccccccCccccccccCcccCCccCccCccCCcCCcCCcCCcCcCcCcccccCcCCcCCcCCcCCcCCcCCcCCcCccCcCCcccCCccCcCcccCCcccCCCcCC

Odszyfruj:

SsSsssssssssSsisssSSSssSsSsSssssssSsSsssssSsSsssSsSssSssSsSSssssSsSssssSSsSssssSSssSssSsSSsssSSSsSssssSsSSsSSsSSsSsSsSssssSSssSssSssSssSssSssSssSssssssSSSsSssSssSSsSsSsssSSsSsssSsSSsSSsSsSSssSSsSSsSSsSSsSSsSSsSSsSSsSSsSSsSsssssssSssssSssssSSssssSSsSssSSsssSssssssssssSsSssSssSssSssSsSSssSSsssSsSsSssSSsssSSSsSsssssssssssssSSssSssSsSsSsssSSssssssssssSsSssssssSsSssssSSsSssSssSSsSssssssssssSSssSsSsSsssssSsSssSsSSSsSssSssSSsSssSssSssSsSsssssSsSsssSSSsSsSssssSsSssSSsSSsSSsSsSSsssSsSSsSSsSSsSSsSSsSSsSSsSSsSSsSsSsssSssSSsssssSsSsssSsssssSsssSsssSssSssSSsSsssssssssssssSSSsssSsSsSsssSsssSSSsSssSssSssSsSSssSssSsSSSsSssssSsSssssssssSsSssSssSsSSssssssSssssssssSsssSSssSssSssSSsSSsSSsSSsSsSsSsssssSsSSsSSsSSsSSsSSsSSsSSsSssSsSSsssSSssSsSsssSSsssSSSsSS

Tłumaczenia Brainfuck:

+>>>+>,<[->[->+>+<<]>[-<+>]<<]>,[>++++[-<-------->]+<<+[<+>+++]<++++++++++>>[>-<-<+<-[>>>+<<<<]<-[+<-]+>>>>]<<[-]>>>[->[-<+<<+>>>]<[->+<]+<<+<<<[>[-]+[>+<+++]>++++++++++[<<->+>->-[<<<+>>>>]-[+>-]+<<<]<<]+>[->>+<<]>>->>-]<<<++++[->++++++++<]>.[-]>,]
+>>>->,<[->[->+>+<<]>[-<+>]<<]>,[>++++[-<-------->]+<<+[<+>+++]<++++++++++>>[>-<-<+<-[>>>+<<<<]<-[+<-]+>>>>]<<[-]>>>[->[-<+<<+>>>]<[->+<]+<<+<<<[>[-]+[>+<+++]>++++++++++[<<->+>->-[<<<+>>>>]-[+>-]+<<<]<<]+>[->>+<<]>>->>-]<<<++++[->++++++++<]>.[-]>,]

oOo CODE to wariant Brainfuck, w którym liczy się tylko wielkość liter.

Zajmuje pierwszy bajt i używa swojego kodu znakowego jako d(więc nowa linia oznacza d = 10). Reszta danych wejściowych to ciąg znaków. EOF wynosi 0.

jimmy23013
źródło
4

GolfScript, 95 64 bajtów, cały kod używany w obu programach

Szyfruj:

0 0z{ 1)'[}??)9t:z21,--/; [84;%zt*84*84$|)21*|$Z!!\~'---|}`{)}%~

Odszyfruj:

1!1{|!2*(\~@@*:u;{32-..0<!\95<&{u+95+95%}*32+}%[""] (...}~a|*~& 

Format wejściowy:

1 "0 0z{ 1)'[}??)9t:z21,--/; [84;%zt*84*84$|)21*|$Z!!\~'---|}`{)}%~"

Wyjaśnienie

Odszyfruj:

1!1                            # Push 0 1.
{                              # Define a block and evaluate it.
    |                          # Or.
    !2*(                       # Get 1 for encryption, or -1 for decryption.
    \~                         # Evaluate the input string.
    @@*:u;                     # u = d for encryption, or -d for decryption.
    {                          # For each character:
        32-                    # Subtract 32.
        ..0<!\95<&             # Test if it is in the printable range.
        {u+95+95%}*            # If so, add u (mod 95).
        32+                    # Add 32 back.
    }%
    [""] (...                  # Push an empty array and 4 empty strings.
}~
a                              # No-op.
|*~                            # Evaluate ""*(""|"") which does nothing.
&                              # Calculate []&"" which is empty.

Szyfruj:

0 0                            # Push 0 0.
z                              # No-op.
{                              # Define a block and get its string representation.
    ...                        # See decryption code.
    |                          # This will be decoded into a }. The string will be truncated here when evaluated.
}`                             # Only the closing } will be truncated, but it is still used as the end of the block.
{)}%                           # Increment each character. Note that the braces before and after the block will also be incremented.
~                              # Evaluate the string.
jimmy23013
źródło
3

JavaScript (wersja robocza ES7) - 167 165 bajtów

Pożyczanie po użyciu ciągów @feersum i użyciu średnika przez @MartinButtner;)

Szyfruj:

J=(s,d)=>s.replace(/[ -~]/g,x=>String.fromCharCode((x.charCodeAt()-32+d)%95+32));J
"eP<T-Qef<V;.95*,.PW$HUG&W0TAef{=;270V/;86k1*;k8-.PPAV,1*;k8-.i=PQS^[U-QMa]S[ZQQc"

Odszyfruj:

"t_Kc<`tuKeJ=HD9;=_f3WdV5f?cPtu+LJAF?e>JGEz@9JzG<=__Pe;@9JzG<=xL_`djib<`\plbji``r"
Y=(s,d)=>s.replace(/[ -~]/g,x=>String.fromCharCode((x.charCodeAt()+63-d)%95+32));Y

Przesunięcie w użyciu: 55

nderscore
źródło
1
Nie działa na puste ciągi znaków. Dlatego musiałem postawić, or <empty string> and <function>a nie tylko or <function>.
feersum
@feersum jest już naprawione ... i 2 bajty krótsze :)
nderscore
Hm, to wygląda znajomo. ;)
Martin Ender,
@ MartinBüttner Nie wiem, co masz na myśli ...;)
nderscore
2

> <> (Ryba) , 467 bajtów

Szyfruj:

ffii{{~~__:0a('0'*!.0a('0'*22(!'(~$~_:}-}$-a*}+{{if~~:i:0({}?;__:{}84{}*__({}?\__:{} _{}70{}g_{})_{}?\4__{}8*-_{}+{}80{}g_%4_{}8*{}+\\sl||||||||||||||||||||||||||||9||||||||||||||9||||||||||||||||||||||||||||||||||||||||||||||||||||9
                                                                              >                      >                              >!;7f7-_{}!%_{}!<872-d_{}!&_{}!<[755(7(%~~_{}!<[55(7(_{}!*!*23a(_{}!'_{}!"55(7((~~_{}~~~o__'4'0.{{{o,

Odszyfruj:

iill~~""bb=3d+*3*-$13d+*3*-55+$*+"'"b=!0!'0d-!.~~li""=l=3+~!B>bb=~!;7~!-bb+~!B_bb=~!#b~!:3~!jb~!,b~!B_7bb~!;-0b~!.~!;3~!jb(7b~!;-~!.__vo                            <              <                                                    <
##############################################################################A######################A##############################A$>:i:0b~!$(b~!$?;:50gb~!$)b~!$?^:88+:+(""b~!$?^88+:+b~!$-$-56d+b~!$*b~!$%88+:++""b~!"""rbb*7*31~~~r/

Oba programy są przesunięte o 3 i przyjmują dane z formularza:

<2-digit offset> <text>

Przesunięcie musi składać się z 2 cyfr, więc należy wprowadzić przesunięcie o wartości 5 05.

To długie przesłanie, ale prawie wszystkie znaki niepełniące są używane przez oba programy . Istnieje wiele białych znaków, które można zdecydowanie zagrać w golfa, ale pomyślałem, że program będzie w ten sposób bardziej interesujący.

Ten obraz pokazuje znaki używane przez oba programy.

Wyjaśnienie

Główną konstrukcją, która to umożliwia, jest _{} -> b~!możliwość dowolnego pomijania znaków w programie deszyfrującym. W jaki sposób?

Encrypt:
  _ : Mirror, but is a no-op if the program flow is horizontal
  { : Shift stack left
  } : Shift stack right

Decrypt:
  b : Push 11 to stack
  ~ : Pop top of stack
  ! : Skip the next instruction

Podsumowując, program szyfrujący nic nie robi, ale program deszyfrujący pomija następną instrukcję. Można to następnie rozszerzyć na _{}! -> b~!$, co pozwala zamiast tego dowolnie pomijać znaki w programie szyfrującym .

Poza tym większość reszty programu wypycha liczby, wykonuje operacje na tych liczbach, a następnie znajduje sposoby na ich wykasowanie. Na przykład użyteczną konstrukcją jest ~~ -> ""wyskakiwanie dwóch wartości dla programu szyfrującego, ale nie wypycha niczego w programie deszyfrującym.


> <>, 149 bajtów

Oto mniej interesująca wersja, która wykorzystuje fakt, że nieprzekazywane instrukcje są skutecznie komentarzami w językach 2D.

Szyfruj:

i68*:@-a*i@@-+i~v
4:v?)g31:;?(0:i:/8
(?v48*-+03g%48*+\*
_~\of0.   .1+1fo/
j*+:zq<6B99A6=qz6g
53Ji?C58/8;?r0?C5:
C?EiJ4r?<EFJ3;EtEg
:tAC5EK8l5tKK86t*i

Odszyfruj:

^+-~/5"V~^55" ^sk
)/k4}\(&/04|%/^/$-
|4k)-~" %(\y)-~ Q~
TsQd[%#ttt#& &[d$
_~ /of1+7..6+2fo+\
*(?^48*-$-04g%48*/
84:^?)g41:;?(0:i:\
/i68*:@-a*i@@-+i~^

Oba programy są przesunięte o 84 i przyjmują dane w taki sam sposób jak powyżej. Pierwsza instrukcja decyduje, którą połowę programu wykonać, z i(wejściem) utrzymującym przepływ programu w prawo w programie szyfrującym i ^przekierowującym przepływ programu w górę (zapętlanie i powrót z dołu) w programie deszyfrującym.

Wyjaśnienie

Dla odpowiedniej połowy programu szyfrującego (program deszyfrujący jest podobny):

i                       read first input digit as char
68*:@-a*                subtract 48 (ASCII "0") and multiply by 10, keeping another 48 on the stack
i                       read second input digit as char
@@-+                    subtract 48 and add to 10*(first digit), giving the offset
i~                      read in space and discard it

--- LOOP ---
:                       copy the offset
i:                      read input char
:0)?;                   check if less than 0 (i.e. EOF) and terminate if so
:13g)?v                 check if greater than ~ in cell (1,3) and drop down if so
48*(?v                  check if less than 32 and drop down if so
48*-+03g%48*+           calculate Caesar shift of the char, fetching 95 from (0,3)

of1+1.                  repeat loop
of0.                    repeat loop

Narzędzie do kodowania

Nie jest to związane z resztą powyższego postu, ale pomyślałem, że opublikuję to, ponieważ muszę go użyć: P.

for(var i=0;i<95;++i){var option=document.createElement("option");option.text=i;document.getElementById("offset").add(option)};function update(m){if(m==1)var code=document.getElementById("in").value;else var code=document.getElementById("out").value;var offset=parseInt(document.getElementById("offset").value);var output="";for(var i=0;i<code.length;i++){var n=code[i].charCodeAt(0);if(n<32||n>127)output+=code[i];else{var c=(n-32+offset*m)%95;output+=String.fromCharCode(c<0?c+95+32:c+32)}}if(m==1)document.getElementById("out").value=output;else document.getElementById("in").value=output};
<html><body><textarea id="in" onkeyup="update(1)" rows=5 style="width:100%"></textarea><textarea id="out" rows=5 style="width:100%" onkeyup="update(-1)"></textarea><select id="offset" onchange="update(1)"></select></body></html>

Sp3000
źródło
1

Perl - 131

Pobiera dane wejściowe z argumentów wiersza poleceń.

We;{for(split//,$ARGV[1]){print chr(((ord$_)-32+$ARGV[0])%95+32)}};q!LUXmYVROZttqi'8-<AvCnaVXOTZeINXmmmUXJiEnrxwri'8-<AuCnj~zpxwnc!

Przesunięcie o 26 daje drugiemu:

q U6!*-B.+'$/IIF>[lapuKwC6+-$)/:}#-BBB*-~>yCGMLE>[lapuJwC?SOEMLC88U,;for(split//,$ARGV[1]){print chr(((ord$_)-32-$ARGV[0])%95+32)};
KSFT
źródło
@Martin Büttner Woah, entuzjazm! To faktycznie nie działa?
KSFT
robi to, o ile wiem;)
Martin Ender