Equivalencia César


24

Dos cadenas son "César equivalente" si la distancia (contando) entre los caracteres correspondientes es la misma. Sí, inventé este término. Aquí hay un ejemplo:

"Abc" y "Cde" son equivalentes porque

distance from a-c == 2
distance from b-d == 2
distance from c-e == 2

La capitalización no hace ninguna diferencia.

"Hola" y "Mundo" no son equivalentes al César porque

distance from h-w == 15
distance from e-o == 10
distance from l-r == 6
distance from l-l == 0
distance from o-d == 15

"Abcd" e "Yzab" son equivalentes de César porque

distance from a-y = 24
distance from b-z = 24
distance from c-a = 24 (it wraps around)
distance from d-b = 24

Debe escribir un programa completo que tome dos cadenas de STDIN e imprima un valor verdadero si son equivalentes a César y un valor falso si no lo son.

Entrada válida

  • Dado que las mayúsculas no importan, es aceptable si su programa requiere que la entrada sea en minúsculas, mayúsculas o cualquier combinación que desee, siempre que esto se especifique en su respuesta.

  • La entrada no tendrá espacios ni signos de puntuación.

  • Las entradas serán de la misma longitud.


8
Hubiera sido bueno permitir la entrada como argumentos de línea de comando. Iba a escribir una solución en C, pero leer desde stdin requiere un código bastante largo, especialmente si no tiene una longitud máxima por adelantado.
Reto Koradi

@RetoKoradi ¿Por qué no? Probablemente no gane de todos modos, ya que C no es exactamente conocido por ser conciso.
DJMcMayhem

Bien, dudo que C alguna vez tenga la oportunidad de una victoria absoluta. En el mejor de los casos, me comparo con soluciones que usan lenguajes de programación "reales"; Pero incluso allí, otros lenguajes tienden a ser más compactos, especialmente si implica el procesamiento de cadenas.
Reto Koradi

44
Cada vez que veo esto en la lista de preguntas, tiene exactamente tantos votos a favor como respuestas.
Alex A.

1
@AlexA. No estaba prestando atención a la proporción de votos positivos para responder hasta que usted lo señaló. Ahora es todo lo que noto.
DJMcMayhem

Respuestas:


10

Pyth, 9 bytes

}wm=.rzGG

Las dos cadenas se esperan en minúsculas, separadas por una nueva línea.

Demostración.

Cómo funciona:

.res la función de traducción rotatoria de Pyth. Mapea cada elemento en el primer argumento desde su primera aparición en el segundo argumento hasta la siguiente entrada en el segundo argumento. En este caso, el segundo argumento es G, el alfabeto en minúsculas, por lo que es equivalente a un desplazamiento César de 1.

Poner un =en frente de la función lo hace en su lugar. Por lo tanto, =.rzGasigna el desplazamiento César de zpor uno a z. Tenga en cuenta que zse inicializa en la primera línea de entrada en Pyth.

Esta expresión se usa dentro de un mapa. m=.rzGGaplica esta transformación a z26 veces, una vez para cada elemento de G, y guarda los resultados en una lista. Esto proporciona la lista de todos los posibles cambios de César z.

Finalmente, }wverifica si la siguiente línea de entrada está en esa lista.


14

CJam, 17 12 11 bytes

1 byte guardado por Dennis.

ll.m26f%)-!

Pruébalo aquí.

Espera que la primera cadena sea minúscula y la segunda sea mayúscula. Imprime 1para cadenas equivalentes a César y de 0otra manera.

Explicación

ll           e# Read two lines of input.
  .m         e# Take the differences of corresponding characters.
    26f%     e# Take the differences modulo 26.
        )-   e# Remove all copies of the last difference from the array. This will 
             e# yield an empty array if and only if all differences are the same.
          !  e# Logical NOT, which yields 1 for an empty array and 0 otherwise.

La razón por la que requerimos la primera cadena en minúsculas y la segunda en mayúsculas es para garantizar que la diferencia sea siempre positiva. De lo contrario, tomar el módulo podría devolver algo negativo y no sería necesariamente único, incluso para cadenas equivalentes a César.


1
Si necesita que la primera palabra esté en minúscula y la segunda en mayúscula, puede usar 26f%para guardar un byte.
Dennis

Puede usar la convención de shell ( stackoverflow.com/questions/2933843/… ) para acercarla a la respuesta de Pyth.
VicAche

1
@VicAche La convención aceptada es interpretar la verdad y la falsedad de la manera que lo interprete su idioma. Además, si elimino el !no tendría 0 o 1 sino una matriz vacía o no vacía.
Martin Ender

9

Python2, 68 67 70 69 Bytes

print len({(ord(y)-ord(x))%26for x,y in zip(*raw_input().split())})<2

Python3, 67 66 bytes

print(len({(ord(y)-ord(x))%26for x,y in zip(*input().split())})<2)

Es un poco difícil deshacerse del golf, así que solo explicando las piezas:

  • zip(*raw_input().split())toma la entrada, la divide en una lista de dos palabras, suponiendo que las palabras estén separadas por espacios en blanco. Después de eso, cada palabra se pasa como un parámetro de la zipfunción, mediante el uso del *operador. La zipfunción creará una lista de pares de letras, para letras en la misma posición.
  • (ord(y)-ord(x))%26for x,y in ... Esto solo transforma la lista de 2 letras en una expresión generadora de las distancias entre esas letras.
  • {...} reduce esta expresión a un conjunto, esencialmente tirando duplicados
  • len(...)<2 comprueba si solo queda un elemento en el conjunto (o 0 para cadenas vacías), lo que esencialmente significa que todas las letras tenían la misma distancia.
  • print produce ese valor

Gracias a xnor por recordarme set(...)se puede reemplazar {...}y forno se requiere el espacio anterior . También gracias a Josay para el <=1de <2optimización.


Bastante similar a mi solución publicada aproximadamente en el mismo minuto. Has sido más inteligente que yo para ingresar, pero puedes reducirlo <=1a '<2'.
SylvainD

1
Puedes hacer una comprensión de conjunto directamente en {...}lugar de hacerlo set((...)). Su código necesita realmente imprimir el resultado.
xnor

@KillianDS Las reglas predeterminadas requieren impresión en STDOUT o devolución (no evaluación REPL), y aquí el OP especificó la impresión. De lo contrario, la forma más corta genérica es utilizar lambdapara ahorrar en escritura printo return.
xnor

1
Por cierto, no tienes el espacio antes for; Python lexer se divide correctamente 26for.
xnor

5

APL (15)

1=≢∪26|-⌿⎕A⍳↑⍞⍞

Necesita que las letras sean mayúsculas, y se imprime 1o 0, así:

      1=≢∪26|-⌿⎕A⍳↑⍞⍞
ABCD
YZAB
1

      1=≢∪26|-⌿⎕A⍳↑⍞⍞
HELLO
WORLD
0

Explicación:

  • ↑⍞⍞: lee dos líneas desde el teclado y organiza los caracteres en una matriz N × 2.
  • ⎕A⍳: para cada carácter, encuentre en qué posición se encuentra ⎕A(el alfabeto en mayúsculas).
  • -⌿: para cada columna, reste el segundo valor del primer valor
  • 26|: tome el mod-26 de cada uno de esos números.
  • Si las cadenas son equivalentes al César, todos los números en esta lista ahora son iguales, entonces:
  • ≢∪: encuentra el número de valores únicos en la lista
  • 1=: compara eso con 1.

Nunca votaré APL :)
orlp

@AlexA .: Estoy usando Dyalog APL 14. Si tienes una Raspberry Pi, es gratis; para los estudiantes también es gratis; de lo contrario, puede descargar una versión no registrada, que es nagware pero funcionalmente idéntica a las reales. dyalog.com TryAPL se basa en esto, por cierto.
Marinus

Me interesaría escuchar sus pensamientos sobre Dyalog vs. GNU APL, ngn / apl y APLX, aunque los comentarios no son realmente el lugar para tal discusión. ;)
Alex A.

3

J, 19 bytes

1=[:#@~.26|-&(3&u:)

Las letras en la misma posición deben tener el mismo caso.

Después de convertir ambas cadenas de entrada a su representación de punto de código con &(3&u:), comparamos 1con la longitud #de la protuberancia ~.del módulo 26 26|de la diferencia -de las dos matrices. La protuberancia será 1si todas las distancias César son iguales.

Uso:

   'abcd' (1=[:#@~.26|-&(3&u:)) 'yzab'
1

Pruébelo en línea aquí.


3

Julia, 91 87 83 bytes

a=readline()
b=readline()
show(length(Set([mod(a[i]-b[i],26)for i=1:length(a)]))<2)

Ungolfed + explicación:

# Read two strings from STDIN
a = readline()
b = readline()

# Get the absolute difference mod 26 of the character values in the strings
x = [mod(a[i] - b[i], 26) for i = 1:length(a)]

# Construct a set consisting of the elements of x. If the set has only a
# single element, the strings are Caesar equivalent. This will print a
# boolean value to STDOUT.
show(length(Set(x)) < 2)

Esto aprovecha el hecho de que las cadenas en Julia se pueden tratar como matrices de caracteres y que las operaciones aritméticas se pueden realizar en valores de caracteres. Las cadenas de entrada pueden tener cualquier combinación de mayúsculas que desee, siempre que la capitalización en cada posición coincida entre las cadenas.


3

C99, 92 bytes con error   101 92 bytes

  r,i;main(z,a)char**a;{for(;z=a[2][++i];)r|=(a[1][i]-z+*a[2]-*a[1]+52)%26;putchar(49-!!r);}

Muy claro; asume que las palabras vienen como primer y segundo argumento, respectivamente. Compilado con -std=c99.


Esto da el resultado incorrecto para la segunda entrada de muestra.
Reto Koradi

Tienes razón, lo extrañé. Fijo.
rr-

3

Javascript ( borrador ES7 ), 87 bytes

Requiere entradas para ser el mismo caso.

(p=prompt)(![z=(a[c='charCodeAt'](i)-b[c](i)+26)%26 for(i in b=p(a=p()))].some(x=>x^z))


2

CJam, 13 bytes

{r(fm26f%}2*=

Requiere que el primer carácter en cada palabra esté en mayúscula, otros en minúscula.

Probar aquí . ( Firefox aquí ).

Lástima que las variantes APL no sean compatibles con la aritmética de personajes ...

Explicación

{
    r       e# Read a word.
    (f-     e# Return each character value minus the first character.
    26f%    e# Mod 26.
}2*         e# Repeat 2 times.
=           e# Check if they are equal.

2

Perl, 80

Editar : una optimización fallida se había deslizado en el código de golf. Ahora coincide con la versión sin golf. (Sin embargo, el recuento de bytes fue correcto).

@a=unpack"W*",<>;for(<>=~/./g){$n=ord()-shift@a;$p=!$c++||$p&&$n==$o;$o=$n}say$p

Ejecutar con Perl versión 5.10 ( perl -M5.10.0o perl -E …) para say(). Versión ligeramente expandida:

@a=unpack"W*",<>;             # read first string, split and convert to numbers

for(<>=~/./g){                # reads the second string and splits it
   $n=ord()-shift@a;          # convert next character of second string and compare
   $p= !$c++ || $p && $n==$o; # compare differences (special case for first char)
   $o=$n
}

say $p

El código genera 1(verdad en Perl) si las cadenas son equivalentes a César, y la cadena vacía (falso en Perl) si no lo son. Si esta interpretación es demasiado floja, necesito agregar 2 bytes para say$p+0, que imprime1 o 0.

El caso de los caracteres debe coincidir entre las entradas.


Según los comentarios sobre la pregunta anterior, también puede tomar la entrada como argumentos de línea de comando. Podría usar -ipara tomar la segunda cadena, que la almacenaría en la variable $^I. Además, el uso en -Elugar de -ecuando se ejecuta en la línea de comando lo conseguirá sayde forma gratuita, por lo que puede usarlo sin agregar bytes. Intenta ejecutar esto: perl -iteststring -E'say$^I'es posible que puedas acortar esto con el -itruco.
hmatt1

Gracias @chilemagic, el -itruco es bueno (¡y no lo sabía!). En este caso no creo que ayude porque $^Ies más largo que <>.
xebtl

@chilemagic Oh, y según esta discusión , no conté los bytes de -M5.10.0todos modos. (Pero mencioné el -Ecambio en la edición)
xebtl

2

Matlab, 49 48 bytes

Esta fue muy rápida. Lamentablemente, obtener una cadena de stdin es bastante costoso.

x=@()input('','s');sum(diff(mod(x()-x(),26)))==0

Tenga en cuenta que, como la mayoría de las respuestas, si no todas, distingue entre mayúsculas y minúsculas.

EDITAR: ¡afeitado un byte definiendo una función anónima!


2

Prólogo, 56 bytes

b([],[],_).
b([A|C],[B|D],N):-N is mod(A-B,26),b(C,D,N).

No todas las combinaciones de casos son compatibles.

uso

b(`abcd`,`yzab`,_).

Pruébalo en línea aquí


2

C, 97 bytes

#define D (*a[2]++-*a[1]+++26)%26
d,r;main(int c,char**a){for(d=D;*a[1];r|=d-D);puts(r?"N":"Y");}

1
¡Hurra! ¡Has restablecido el equilibrio!
DJMcMayhem

Puede guardar 4 caracteres si reutiliza dy declara ael tipo fuera de parámetros como este: d,r;main(int c,char**a){r;main(d,a)char**a;{
rr-

1

Scala, 57 bytes

(readLine zip readLine map(x=>x._1-x._2%26)toSet).size==1

Poco más que los demás, y esencialmente equivalente, ¡pero tiene un estilo de lenguaje diferente!

También tengo esta versión (56 bytes):

(readLine zip readLine map(_._1-x$1._2%26)toSet).size==1

Pero no sé si el trabajo x $ 1 es una coincidencia o por diseño ...


1
Eso es realmente extraño, ¿cómo x$1funciona sin xser definido?
Dan Getz

@DanGetz Estoy bastante seguro de que es una casualidad compiladora. Puedo hacer una pregunta sobre el desbordamiento de la pila al respecto: D
Otros

1

Python 2, 80 bytes

Toma 2 cadenas de caracteres similares de stdin separadas por un espacio:

s,t=raw_input().split();print len(set((ord(c)-ord(d))%26 for c,d in zip(s,t)))<2

Probado en los siguientes casos de prueba:

tests = [
    ("abc", "abc", True),
    ("abcd", "abc", False),
    ("abc", "cde", True),
    ("Abc", "Cde", True),
    ("abc", "deg", False),
    ("Hello", "World", False),
    ("Abcd", "Yzab", True),
    ("", "", True)
]

for s, t, v in tests:
    if len(s) == len(t): # I didn't read that at first
        assert v == (len(set((ord(c) - ord(d)) % 26 for c, d in zip(s, t))) < 2)

1

Pitón 2 - 241 237 188 147 Bytes

Toma la entrada como una cadena en minúsculas entre comillas, separadas por espacios. Tiene que haber una mejor manera..

s=[[ord(x)for x in y]for y in input().split()];v=[];v=[v+[(s[1][i]-s[0][i])%26]for i in xrange(0,len(s[0]))];v=sum(v,[]);print sum(v)//v[0]==len(v)

Sin golf (260 bytes impares)

strs = [[ord(x) for x in y] for y in raw_input().split()]
vals = []
for i in xrange(0, len(strs[0])):
if strs[0][i]<strs[1][i]:
    vals += [strs[1][i]-strs[0][i]]
else:
    vals += [26-(strs[0][i]-strs[1][i])]
return sum(vals)//vals[0] == len(vals)

Estoy seguro de que puede hacer que todas las variables tengan 1 carácter de largo y guardar un montón de bytes. También debe agregar 4 a su puntaje, ya que espera 4 "s adicionales en su entrada.

@Reticalidad No puedo creer que no haya acortado las variables ... movimiento amateur. Agregué 2 al conteo de bytes, ya que no lo expliqué correctamente; la entrada funciona como "abc cde".
Kade

1

R, 83 84

Bastante más o menos lo mismo que las otras soluciones. Convierte las cadenas en un vector de enteros. Modifique la diferencia de los vectores por 26. Haga un único sobre la lista ya que verifique que la longitud sea 1. Se espera que el caso sea el mismo en los caracteres correspondientes en cada cadena.

length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2

Espera a que se ingresen las dos cadenas

> length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2
abcdefghijklmnopqrstuvwxyz
opqrstuvwxyzabcdefghijklmn
[1] TRUE
> length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2
Hello
World
[1] FALSE
> length(unique(((S=strtoi)((R=charToRaw)((I=readline)()),16L)-S(R(I()),16L))%%26))<2
Bob
Nan
[1] TRUE
>

Puede guardar un byte utilizando en <2lugar de ==1.
Alex A.

Puede guardar 3 bytes simplemente 10

@AlexA. Gracias Alex, me perdí esa ... y ahora la extraño :)
MickyT

@Reticality: ¿Cómo?
Alex A.

@Reticality Desafortunadamente, devolvería 1 o más de uno.
MickyT

1

Matlab / Octave, 53 52

x=@()input('','s');isscalar(unique(mod(x()-x(),26)))

La entrada debe ser del mismo caso.

Lamentablemente, Matlab no es muy bueno con la entrada del usuario. Como identificador anónimo, esto podría tener solo 35 bytes:

@(a,b)isscalar(unique(mod(a-b,26)))

Matlab trata los caracteres de una cadena como un vector de números. Hacer resta nos da su diferencia y uniqueconvierte ese vector en un vector que contiene solo valores únicos. Si solo hay un número, las palabras son equivalentes de césar y isscalar devuelve 1; de lo contrario, devolverá 0.


Oh! ¡Otra entrada de Matlab! Miré las respuestas solo después de contestarme.
Oebele

acabo de descubrir que puede guardar un byte definiendo x = @ () input ('', 's');
Oebele

@Oebele ¡Gracias! Creo que voy a comenzar a intentar más problemas de golf en Matlab, lo he encontrado bastante divertido.
FryAmTheEggman

Sí lo es. Para muchos problemas puede ser muy conciso con su material basado en matriz. Octave tiene un poco más de sintaxis libre, que a veces también puede ahorrar algunos bytes más, como la definición de variable en línea.
Oebele

1

bash, 71 48

Usando el programa "estándar" de Unix caesar(6) .

Nueva versión (con mucha ayuda de @DigitalTrauma):

read a b;seq -f"caesar %g <<<$a" 26|bash|grep $b
  • Las entradas deben estar en la misma línea, separadas por espacios
  • El caso de los caracteres debe coincidir entre las entradas.
  • Imprime 1para verdadero o nada para falso.

Si se permite la entrada a través de argumentos de línea de comando, se puede acortar a 39 bytes :

 seq -f"caesar %g <<<$1" 26|bash|grep $2

Versión antigua para el registro:

 read a b;for i in `seq 26`;do [ `echo $a|caesar $i` = $b ]&&echo 1;done

48 bytes, según mi recuento: read a b;seq -f"caesar %g <<<$a" 26|bash|grep $bel resultado está en la $?variable integrada, donde 0 == FALSO y 1 == VERDADERO, según la semántica de shell estándar.
Trauma digital

@DigitalTrauma ¡Esas son algunas ideas ingeniosas! Me gusta especialmente el seq -f | bashbit. El resultado $?no es válido al leer el desafío, pero al igual que mi código, el suyo no genera nada falso y algo verdadero (excepto en el caso límite de dos cadenas de entrada vacías). De todos modos, se sentiría como una trampa usar todo esto en mi respuesta, tal vez deberías enviar la tuya.
xebtl

No se preocupe, le estoy ofreciendo los consejos de golf para que los use. Si quisiera usarlos, ya lo habría hecho :). En cuanto a lo verdadero / falso, tiendo a interpretar que es lo verdadero y lo falso en su idioma dado: intente [ 0 == 0 ] ; echo $?y[ 0 == 1 ] ; echo $?
Trauma digital

1

> <> (Pescado) , 50 bytes

i:3b*(?v88+0.;n1<
0)?vc1.>~ri-&l?!^i-&:&-2d*%
;n0<

Espera que las letras en la misma posición tengan el mismo caso.

Explicación

  • i:3b*(?vlee la primera palabra en la pila al 88+0.proporcionar el salto en bucle
  • ~ri-&elimina ~el espacio de separación de la pila, invierte la pila r(la primera letra estará en la parte superior), lee la primera letra de la segunda palabra i, calcula el desplazamiento de la primera letra de la primera palabra -y la almacena en el registro &.
  • l?!^i-&:&-2d*%0)?vlee cada letra siguiente de la segunda palabra restándola de la letra correspondiente de la primera palabra que está en la parte superior de la pila resta el desplazamiento &:&-almacenado en el registro y comprueba si el resultado es 0 mod 26 2d*%. Si no imprime 0 y termina 0n;. c1.proporciona el salto en bucle.
  • Si llega al final de la segunda palabra, el programa imprime 1 y finaliza 1n;.

0

KDB (Q), 35 bytes

{0=sum(1_-':)mod[;26](-)."i"$(x;y)}

Explicación

                         "i"$(x;y)      / convert to ascii decimal
                     (-).               / get differences
             mod[;26]                   / mod 26
      (1_-':)                           / difference between the differences
 0=sum                                  / sum should be 0 if equivalent
{                                 }     / lambda

Prueba

q){0=sum(1_-':)mod[;26](-)."i"$(x;y)}["abcd";"yzab"]
1b

0

Java 281

import java.util.*;enum C{E;Scanner s=new Scanner(System.in);public static void main(String[]z){char[]u=E.n(),v=E.n();int i=0,d=(u[0]-v[0]+26)%26;boolean e=true;for(;++i<u.length;)e&=d==(u[i]-v[i]+26)%26;System.out.print(e);}char[]n(){return s.next().toUpperCase().toCharArray();}}

expandido:

import java.util.*;
enum Caesar{
    Equivalence;
    Scanner input=new Scanner(System.in);
    public static void main(String[]z){
        char[]firstString=Equivalence.nextInput(),secondString=Equivalence.nextInput();
        int index=0,difference=(firstString[0]-secondString[0]+26)%26;
        boolean isEqual=true;
        for(;++index<firstString.length;)
            isEqual&=difference==(firstString[index]-secondString[index]+26)%26;
        System.out.print(isEqual);
    }
    char[]nextInput(){
        return input.next().toUpperCase().toCharArray();
    }
}

Podría ahorrar 14 bytes si me deshago de convertir todo a mayúsculas, pero siento que es más completo dejarlo.


0

Jalea , 5 bytes

Oạ/ċ2

Pruébalo en línea!

Emite un entero positivo para equivalente, 0 de lo contrario

Cómo funciona

Oạ/ċ2 - Main link. Argument A (a list of strings)  e.g. ["abc", "cde"]

O     - Ordinal. Cast to code point                     [[97, 98, 99], [99, 100, 101]]
  /   - Reduce the list by...
 ạ    -   absolute difference                           [2, 2, 2]
   ċ2 - Count the number of 2s in the list              3
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.