Shift Caesars Shifts

13

Descripción

Un César Shift es un cifrado monoalfabético muy simple en el que cada letra se reemplaza por la siguiente en el alfabeto. Ejemplo:

Hello world! -> IFMMP XPSME!

( IBSLR, EGUFV!es la salida para el desafío real, este fue un ejemplo de desplazamiento por 1.)

Como puede ver, el espacio y la puntuación permanecen sin afinar. Sin embargo, para evitar adivinar el mensaje, todas las letras están en mayúscula. Al cambiar las letras hacia atrás, el mensaje fue descifrado, conveniente, pero también muy fácil de descifrar por otras personas que se supone que no saben lo que significa el mensaje.

Por lo tanto, estaremos ayudando a César un poco mediante el uso de una forma avanzada de su cifrado: ¡el Cambio de César con cambio propio !

Desafío

Su tarea es escribir un programa o función que, dada una cadena para cifrar, genere la cadena cifrada correspondiente a la entrada. El avanzado Caesar Shift funciona así:

1. Compute letter differences of all adjacent letters: 
    1.1. Letter difference is computed like this:

         Position of 2nd letter in the alphabet
        -Position of 1st letter in the alphabet
        =======================================
                              Letter difference

    1.2. Example input: Hello
         H - e|e -  l|l  -  l|l  -  o
         7 - 5|5 - 12|12 - 12|12 - 15 Letter differences: 3; -7; 0; -3
            =3|   =-7|     =0|    =-3

2. Assign the letters continously a letter difference from the list,
   starting at the second letter and inverting the differences:
    2.1. 2nd letter: first difference, 3rd letter: second difference, etc.

    2.2. The first letter is assigned a 1.

    2.3. Example input: Hello with differences 3; -7; 0; -3

         Letter || Value
         =======||======
            H   ||   1
            E   ||  -3
            L   ||   7
            L   ||   0
            O   ||   3

3. Shift the letters by the value x they have been assigned:
    3.1. In case of a positive x, the letter is shifted x letters to the right.
    3.2. In case of a negative x, the letter is shifted |x| letters to the left.
    3.3. In case of x = 0, the letter is not shifted.

    3.4. If the shift would surpass the limits of the alphabet, it gets wrapped around
         Example: Y + Shift of 2 --> A

    3.5. Example input: See the table under 2.3.

                ||       || Shifted
         Letter || Value || Letter
         =======||=======||=========
            H   ||   1   ||    I
            E   ||  -3   ||    B     Program output:
            L   ||   7   ||    S     IBSLR
            L   ||   0   ||    L
            O   ||   3   ||    R

Los espacios y otros símbolos especiales, como la puntuación, se omiten en este proceso. Se garantiza que su programa recibirá una cadena que solo contiene caracteres ASCII imprimibles. La salida de su función / programa solo debe estar en mayúscula.

Este es el , por lo que se aplican las lagunas estándar, ¡y que gane la respuesta más corta en bytes!

racer290
fuente
2
No es E -3 ?
Leaky Nun
3
¿Qué pasa si la diferencia de letras saca la letra del alfabeto? Me gusta ZEN, por ejemplo. Zdesplazado por 1 es ... A? (como nota al margen, la respuesta 05AB1E se convierte Zen A)
Sr. Xcoder
66
Casos de prueba por favor. Además, ¿qué caracteres se omiten exactamente? ¿Y qué significa para ellos ser omitidos? ¿Se eliminan por completo o deben permanecer en la salida?
Luis Mendo
1
@Giuseppe ve las respuestas votadas para los casos de prueba, OP las ha validado como correctas, supongo, o tendrían votos negativos.
Magic Octopus Urn
2
¿Se refería a palabras como RELIEFy RELIESpara cifrar el mismo resultado SRSFAG?
Anders Kaseorg

Respuestas:

5

05AB1E , 28 27 24 bytes

láÇ¥R`XIlvyaiAyk+Aèëy}u?

Pruébalo en línea!

Explicación

l                          # convert input to lower case
 á                         # keep only letters
  ǥ                       # compute deltas of character codes
    R`                     # reverse and push separated to stack
      X                    # push 1
       Ilv                 # for each char y in lower case input
          yai              # if y is a letter
             Ayk           # get the index of y in the alphabet
                +          # add the next delta
                 Aè        # index into the alphabet with this
            ëy             # else push y
              }            # end if
            u?             # print as upper case
Emigna
fuente
Cada uno obtendrá IBSLR, EGUFV!para Hello, World!, ¿es correcto? ¿OP acaba de estropear ese ejemplo?
Magic Octopus Urn
1
@MagicOctopusUrn: Su ejemplo al principio solo muestra lo que es un cambio. Simplemente se desplaza en 1 letra, por lo que es bastante engañoso.
Emigna
4

Python 3 , 100 bytes

b=0
for c in map(ord,input().upper()):
 if 64<c<91:b,c=c,(c+c-(b or~-c)-65)%26+65
 print(end=chr(c))

Pruébalo en línea!

brealiza un seguimiento del código ASCII de la última letra, o es inicialmente cero; la fórmula c+c-(b or~-x)significa que una letra con código ASCII cse desplaza por c-bsib no es cero y c-(c-1) == +1si bes cero (para la primera letra).

b nunca volverá a ser cero, ya que se garantiza que la cadena constará de caracteres ASCII imprimibles .

Finalmente, 64<c<91verifica sic es una letra ASCII en mayúsculas y (…-65)%26+65vuelve a colocar todo en el A-Zrango.

ovs guardaron un byte. ¡Gracias!

Lynn
fuente
100 bytes
ovs
1

ES6 (Javascript), 138 bytes:

s=>((s,a,f)=>((r=i=>s[i]&&(a[i]=String.fromCharCode((2*s[f](i)-(s[f](i-1)||71)-38)%26+64),r(i+1)))(0),a))(s.toUpperCase(),[],"charCodeAt")

http://jsbin.com/manurenasa/edit?console

Jonas Wilms
fuente
no se saltea las letras, parece?
Titus
1

MATL , 27 bytes

tXkt1Y2mXH)tlwdh+64-lY2w)H(

Pruébalo en línea!

Creo que esto es lo más corto que puedo obtener, pero hay muchas variedades diferentes ya que hay muchas reutilizaciones de 'variables' (hay 3 t(duplicación) y 2 woperaciones (intercambio), Hse usa el portapapeles y incluso entonces todavía hay un duplicado1Y2 ...). Lamentablemente, no pude guardar bytes con el Mportapapeles automático .

Más de la mitad del programa está dedicado a ponerlo en mayúsculas e ignorar los caracteres no alfabéticos: solo el cifrado no tiene más de 13 bytes (¡ Pruébelo en línea! )

Sanchises
fuente
1

Perl, 90 89

Aunque los lenguajes que no son codegolf rara vez son competitivos, podemos ir por debajo de 100;)

@a=split//,<>;say uc(++$a[0]).join'',map{uc chr(2*ord($a[$_+1])-ord($a[$_])+!$_)}0..$#a-1

He decidido deshacer esto:

@a = split//,<>; Toma información de STDIN, almacena la lista de caracteres (¡con nueva línea!) En @a.

say uc(++$a[0])la primera letra mayúscula de salida se desplazó por 1. Resulta que puede incrementar una letra en perl si usa un prefijo ++. Este es un mutador de c.

2*ord($a[$_+1])-ord($a[$_])+!$_Se nos pide que tomemos un carácter en x y agreguemos la diferencia + (x- (x-1)). Bueno, eso es 2x - (x-1). Sin embargo: ¡cambié la primera letra! Entonces tengo que corregir ese error, por lo tanto+!$_ lo , que corregirá por haber restado uno demasiado en la posición 0 (¡solo el caso! $ _ No es undef). Luego debemos uc chrobtener una letra mayúscula del valor ASCII calculado.

map{ ... } $#a-2 - $#a es la posición para acceder al último elemento de la matriz. Como estoy agregando uno, quiero$#a-1 , pero debido a que la nueva línea de entrada necesita ignorarse, esto es $#a-2.

Esto se concatena con la primera letra, y hemos terminado :)

bytepusher
fuente
Esto parece tener algunos problemas al tratar con las compensaciones que se envuelven alrededor del alfabeto y con caracteres no alfabéticos. Pruébalo en línea!
Xcali
1

Perl 5 -F , 73 77 74 bytes

/\w/&&($_=chr 65+(2*($n=ord uc)-65-($!||-1+ord uc))%26)&($!=$n)for@F;say@F

Pruébalo en línea!

Xcali
fuente
Esto no omite totalmente las no letras; simplemente no los convierte. Creo que Hello, World!debería resultar IBSLR, EGUFV!, no IBSLR, XGUFV!.
Titus
Tienes razón. Se corrigió con 4 bytes más para preservar la letra anterior.
Xcali
1

PHP, 106 98 bytes

bastante desagradable ese ... si base_convertno fuera tan largo (o ctype_alpha) ...
pero lo obtuve por debajo de 100. satisfecho.

for(;$a=ord($c=$argn[$i++]);print ctype_alpha($c)?chr(65+($p?(25-$p+2*$p=$a)%26:$p=$a)):$c)$a&=31;

Ejecutar como tubería -nRo probarlo en línea .

Titus
fuente