César-Cypher-Mania

22

El Caesar Cypher es un cifrado de sustitución muy simple donde cada letra se desplaza por un desplazamiento fijo (girando alrededor de Z a A). Del mismo modo, también podemos utilizar un cifrador César para el conjunto de caracteres ASCII imprimibles. Estos son los 95 caracteres de los puntos de código 0x20 a 0x7E. Para un desplazamiento dado d, asignamos el punto de código Ca

(C - 32 + d) % 95 + 32

que desplaza a todos los caracteres por a dy gira alrededor del ~espacio. Los caracteres fuera de este rango (caracteres de control como líneas nuevas, pestañas y caracteres fuera del rango ASCII) no se ven afectados.

Debe escribir dos programas o funciones (potencialmente en diferentes idiomas), que toman un desplazamiento dy una cadena. El primer programa debe devolver o imprimir el cifrado César de la entrada. El segundo programa debe devolver o imprimir el cifrado César inverso (es decir, usar desplazamiento -d). Puede recibir información a través de STDIN, argumento de línea de comando o argumento de función.

Para hacer las cosas más interesantes, el segundo programa debe ser un cifrado César del primer programa. Es decir, si se pasa el código fuente del primer programa a sí mismo, para algún desplazamiento distinto de cero d, la salida debe ser el segundo programa.

Ambos programas, así como las cadenas de entrada, deben contener solo caracteres ASCII imprimibles, líneas nuevas y pestañas. Ninguno de los programas puede contener comentarios o leer su propio código fuente, nombre de archivo o ID de proceso directa o indirectamente.

Este es el código de golf, por lo que gana la respuesta más corta (en bytes). Como ambos programas deben tener el mismo tamaño, solo necesita contarlo una vez.

Martin Ender
fuente

Respuestas:

12

Cjam, 40 38 37 bytes

Cifrado Adelante:

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

Cifrado inverso:

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

y el segundo programa es el cifrado del primero con diferencia de 2


Cómo funciona

Se me ocurrió esta respuesta por pura suerte mientras probaba cosas.

Primero, las partes de 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";

Ahora viene la explicación de la parte difícil.

Las transformaciones clave son

<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

Entonces el primer programa es

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

Y el segundo programa es

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

La entrada es como "<escaped string to be cyphered>" <difference>

Por ejemplo:

"abcd" 4

y la salida del primer programa es

efgh

y del segundo programa es

]^_`

Pruébalo en línea aquí

Optimizador
fuente
¿No son 40 bytes? también da un error en el intérprete en línea (algo en Arraylists no se está implementando)
Def
@Deformyer corrigió el recuento de bytes. ¿Cómo estás dando la entrada?
Optimizador
Sí, mi mal, utilicé los argumentos en el orden incorrecto.
Def
'"q ~' ~), 32> _ @ m <er" 9} o |% | '* 10 <]> k <cp}] "_-" 2' no funciona (java.lang.RuntimeException: Inesperado})
Def
1
@Deformyer Tienes que escapar de las comillas en esa cadena
Optimizer
7

Pitón 2, 147

Claramente, no pensé demasiado en este, ya que sería inútil en Python. Simplemente hay dos programas separados, con el no utilizado encerrado en una cadena.

El desplazamiento entre los dos programas es 39.

Adelante

Define la función Z aceptando una cadena Unicode y un desplazamiento.

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"

Inverso

Define la función I aceptando una cadena Unicode y un desplazamiento.

"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
fuente
5

Python 3: 248 bytes

Mi objetivo era hacer esto como Python one-liner. Objetivo de éxito, pero ahora no me puedo molestar en jugar golf.

Cifrar:

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'

Descifrar:

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

Editar: corregido para no afectar los caracteres fuera del rango ASCII imprimible

El desplazamiento de encriptar a desencriptar es 20. Use ingresando primero el desplazamiento, luego la cadena, por ej.

5
hello

Explicación

Las siguientes transformaciones son la clave:

r -> '
' -> ;

El primero permite el uso de or, mientras que el segundo ignora una cadena por punto y coma.

Tenga en cuenta que "".__doc__[2]devuelve la cadena r(tomada de str). Esto es necesario para evitar que la cadena entre comillas simples en el programa de descifrado tenga comillas parásitas en el medio.

Sp3000
fuente
5

Rubí, 131125 bytes

Aquí está mi propia presentación (que había escrito anteriormente como prueba de concepto, pero logré violar mis propias reglas de alguna manera). No estoy reutilizando ningún código entre las dos presentaciones (quiero que ustedes superen esto, después de todo), sino que consiste en dos líneas, una de las cuales se convierte en una cadena con galimatías.

Cifrado delantero:

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"

Cifrado inverso:

"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

Ambos fragmentos definen una función (llamada Yen la primera y Jen la segunda), que toma un número entero y una cadena e imprime la cadena transformada en STDOUT. El desplazamiento entre las dos piezas de código es 40.

Martin Ender
fuente
4

oOo CODE , 750 744 bytes, todo el código utilizado en ambos programas

Demasiado tiempo, pero probablemente sea la herramienta adecuada para hacerlo ...

Cifrar:

CcCcccccccccCcYcccCCCccCcCcCccccccCcCcccccCcCcccCcCccCccCcCCccccCcCccccCCcCccccCCccCccCcCCcccCCCcCccccCcCCcCCcCCcCcCcCccccCCccCccCccCccCccCccCccCccccccCCCcCccCccCCcCcCcccCCcCcccCcCCcCCcCcCCccCCcCCcCCcCCcCCcCCcCCcCCcCCcCCcCcccccccCccccCccccCCccccCCcCccCCcccCccccccccccCcCccCccCccCccCcCCccCCcccCcCcCccCCcccCCCcCcccccccccccccCCccCccCcCcCcccCCccccccccccCcCccccccCcCccccCCcCccCccCCcCccccccccccCCccCcCcCcccccCcCccCcCCCcCccCccCCcCccCccCccCcCcccccCcCcccCCCcCcCccccCcCccCCcCCcCCcCcCCcccCcCCcCCcCCcCCcCCcCCcCCcCCcCCcCcCcccCccCCcccccCcCcccCcccccCcccCcccCccCccCCcCcccccccccccccCCCcccCcCcCcccCcccCCCcCccCccCccCcCCccCccCcCCCcCccccCcCccccccccCcCccCccCcCCccccccCccccccccCcccCCccCccCccCCcCCcCCcCCcCcCcCcccccCcCCcCCcCCcCCcCCcCCcCCcCccCcCCcccCCccCcCcccCCcccCCCcCC

Descifrar:

SsSsssssssssSsisssSSSssSsSsSssssssSsSsssssSsSsssSsSssSssSsSSssssSsSssssSSsSssssSSssSssSsSSsssSSSsSssssSsSSsSSsSSsSsSsSssssSSssSssSssSssSssSssSssSssssssSSSsSssSssSSsSsSsssSSsSsssSsSSsSSsSsSSssSSsSSsSSsSSsSSsSSsSSsSSsSSsSSsSsssssssSssssSssssSSssssSSsSssSSsssSssssssssssSsSssSssSssSssSsSSssSSsssSsSsSssSSsssSSSsSsssssssssssssSSssSssSsSsSsssSSssssssssssSsSssssssSsSssssSSsSssSssSSsSssssssssssSSssSsSsSsssssSsSssSsSSSsSssSssSSsSssSssSssSsSsssssSsSsssSSSsSsSssssSsSssSSsSSsSSsSsSSsssSsSSsSSsSSsSSsSSsSSsSSsSSsSSsSsSsssSssSSsssssSsSsssSsssssSsssSsssSssSssSSsSsssssssssssssSSSsssSsSsSsssSsssSSSsSssSssSssSsSSssSssSsSSSsSssssSsSssssssssSsSssSssSsSSssssssSssssssssSsssSSssSssSssSSsSSsSSsSSsSsSsSsssssSsSSsSSsSSsSSsSSsSSsSSsSssSsSSsssSSssSsSsssSSsssSSSsSS

Traducciones de Brainfuck:

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

oOo CODE es una variante de Brainfuck donde solo importa el caso de las letras.

Toma el primer byte y usa su código de carácter como d(por lo que una nueva línea significa d = 10). El resto de la entrada es la cadena. EOF es 0.

jimmy23013
fuente
4

GolfScript, 95 64 bytes, todo el código utilizado en ambos programas

Cifrar:

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

Descifrar:

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

Formato de entrada:

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

Explicación

Descifrar:

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.

Cifrar:

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
fuente
3

Javascript (borrador ES7) - 167 165 bytes

Tomando prestado del uso de cadenas de @feersum y del uso de punto y coma de @MartinButtner;)

Cifrar:

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"

Descifrar:

"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

Offset para usar: 55

nderscore
fuente
1
Falla para cadenas vacías. Es por eso que tuve que poner en or <empty string> and <function>lugar de solo or <function>.
feersum
@feersum ahora está arreglado ... y 2 bytes más corto :)
nderscore
Hm, esto parece familiar. ;)
Martin Ender
@ MartinBüttner No sé a qué te refieres ...;)
nderscore
2

> <> (Pez) , 467 bytes

Cifrar:

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,

Descifrar:

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/

Los dos programas están compensados ​​por 3, y toman la entrada de la forma:

<2-digit offset> <text>

El desplazamiento debe ser de 2 dígitos, por lo que se debe ingresar un desplazamiento de 5 como 05.

Esta es una presentación larga, pero casi todos los caracteres sin relleno son utilizados por ambos programas . Hay mucho espacio en blanco que definitivamente se puede jugar, pero pensé que el programa sería más interesante de esta manera.

Esta imagen resalta los caracteres utilizados por ambos programas.

Explicación

La construcción principal que hace esto posible es _{} -> b~!, lo que permite omitir arbitrariamente los caracteres en el programa de descifrado. ¿Cómo?

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

Con todo, el programa de cifrado no hace nada, pero el programa de descifrado omite la siguiente instrucción. Esto puede extenderse a _{}! -> b~!$, lo que permite omitir caracteres de forma arbitraria en el programa de cifrado .

Aparte de esto, la mayoría del resto del programa está presionando números, realizando operaciones en esos números y luego encontrando formas de hacerlos explotar. Por ejemplo, una construcción útil es ~~ -> "", que muestra dos valores para el programa de cifrado, pero no introduce nada en el programa de descifrado.


> <>, 149 bytes

Aquí está la versión menos interesante, que utiliza el hecho de que las instrucciones que no se pasan son efectivamente comentarios en lenguajes 2D.

Cifrar:

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

Descifrar:

^+-~/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~^

Los dos programas están compensados ​​por 84 y toman la entrada de la misma manera que arriba. La primera instrucción decide qué mitad del programa ejecutar, con i(entrada) manteniendo el flujo del programa hacia la derecha en el programa de cifrado, y ^redirigiendo el flujo del programa hacia arriba (dando vueltas y regresando desde la parte inferior) en el programa de descifrado.

Explicación

Para la mitad relevante del programa de cifrado (el programa de descifrado es similar):

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

Herramienta de codificación

Esto no está relacionado con el resto de la publicación anterior, pero pensé en publicar esto porque necesito usarlo: 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
fuente
1

Perl - 131

Toma información de los argumentos de la línea de comando.

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

Cambiarlo por 26 le da al otro:

q U6!*-B.+'$/IIF>[lapuKwC6+-$)/:}#-BBB*-~>yCGMLE>[lapuJwC?SOEMLC88U,;for(split//,$ARGV[1]){print chr(((ord$_)-32-$ARGV[0])%95+32)};
KSFT
fuente
@Martin Büttner Woah, ¡un voto a favor! En realidad hace el trabajo?
KSFT
lo hace hasta donde puedo decir;)
Martin Ender