Equivalenza di Cesare


24

Due stringhe sono "Caesar equivalenti" se la distanza (contando verso l'alto) tra i caratteri corrispondenti è la stessa. Sì, ho inventato questo termine. Ecco un esempio:

"Abc" e "Cde" sono equivalenti perché

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

La capitalizzazione non fa alcuna differenza.

"Ciao" e "Mondo" non sono equivalenti a Cesare perché

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" sono equivalenti a Cesare perché

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

Devi scrivere un programma completo che prende due stringhe da STDIN e stampa un valore veritiero se sono equivalenti a Cesare, e un valore falso se non lo sono.

Input valido

  • Poiché le maiuscole non contano, è accettabile se il tuo programma richiede che l'input sia tutto minuscolo, tutto maiuscolo o qualunque combinazione tu voglia, purché sia ​​specificato nella tua risposta.

  • L'input non avrà spazi o punteggiatura.

  • Gli ingressi avranno la stessa lunghezza.


8
Sarebbe stato bello consentire l'input come argomenti della riga di comando. Stavo per scrivere una soluzione C, ma la lettura da stdin richiede un codice abbastanza lungo, soprattutto se non hai una lunghezza massima in anticipo.
Reto Koradi,

@RetoKoradi Perché no? Probabilmente non vincerà comunque, poiché C non è esattamente noto per essere conciso.
DJMcMayhem

Giusto, dubito che C avrebbe mai avuto la possibilità di una vittoria assoluta. Nella migliore delle ipotesi, confronto con soluzioni che utilizzano linguaggi di programmazione "reali";). Ma anche lì, altre lingue tendono ad essere più compatte, in particolare se si tratta dell'elaborazione di stringhe.
Reto Koradi,

4
Ogni volta che vedo questo nella lista delle domande, ha esattamente tanti voti quanti sono le risposte.
Alex A.

1
@AlexA. Non ho prestato attenzione al voto positivo per rispondere al rapporto fino a quando non lo hai sottolineato. Ora è tutto ciò che noto.
DJMcMayhem

Risposte:


10

Pyth, 9 byte

}wm=.rzGG

Le due stringhe sono previste in minuscolo, newline separate.

Dimostrazione.

Come funziona:

.rè la funzione di traduzione rotativa di Pyth. Mappa ogni elemento nel primo argomento dalla prima occorrenza nel secondo argomento alla voce successiva nel secondo argomento. In questo caso, il secondo argomento è Gl'alfabeto minuscolo, quindi questo equivale a uno spostamento di Cesare di 1.

Mettere un =davanti alla funzione la rende sul posto. Quindi, =.rzGassegna il turno di Cesare di zuno a z. Si noti che zè inizializzato sulla prima riga di input in Pyth.

Questa espressione viene utilizzata all'interno di una mappa. m=.rzGGapplica questa trasformazione a z26 volte, una volta per ogni elemento di G, e salva i risultati in un elenco. Questo fornisce l'elenco di tutti i possibili turni di Cesare z.

Infine, }wcontrolla se la riga successiva di input è in quell'elenco.


14

CJam, 17 12 11 byte

1 byte salvato da Dennis.

ll.m26f%)-!

Provalo qui.

Si aspetta che la prima stringa sia in minuscolo e la seconda in maiuscolo. Stampa 1per stringhe equivalenti a Cesare e 0non.

Spiegazione

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.

Il motivo per cui richiediamo la prima stringa in minuscolo e la seconda in maiuscolo è garantire che la differenza sia sempre positiva. Altrimenti, prendere il modulo potrebbe restituire qualcosa di negativo e non sarebbe necessariamente unico, anche per le stringhe equivalenti a Cesare.


1
Se è necessario che la prima parola sia in minuscolo e la seconda in maiuscolo, è possibile utilizzare 26f%per salvare un byte.
Dennis,

Puoi usare la convenzione shell ( stackoverflow.com/questions/2933843/… ) per avvicinarla alla risposta Pyth.
VicAche,

1
@VicAche La convenzione accettata è di interpretare la verità e la falsità in qualunque modo la tua lingua la interpreti. Inoltre, se rimossi il !non avrei 0 o 1 ma un array vuoto o non vuoto.
Martin Ender,

9

Python2, 68 67 70 69 byte

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

Python3, 67 66 byte

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

È un po 'difficile ungolf, quindi basta spiegare i pezzi:

  • zip(*raw_input().split())accetta l'input, lo divide in un elenco di due parole, assumendo che le parole siano separate da spazi bianchi. Successivamente, ogni parola viene passata come parametro della zipfunzione, mediante l' *operatore. La zipfunzione creerà un elenco di coppie di lettere, per le lettere nella stessa posizione.
  • (ord(y)-ord(x))%26for x,y in ... Questo trasforma semplicemente l'elenco di 2 lettere in un'espressione generatrice delle distanze tra quelle lettere.
  • {...} riduce questa espressione a un set, essenzialmente eliminando i duplicati
  • len(...)<2 controlla se nell'insieme è rimasto solo un elemento (o 0 per stringhe vuote), il che significa essenzialmente che tutte le lettere avevano la stessa distanza.
  • print genera quel valore

Grazie a xnor per avermi ricordato, set(...)può essere sostituito {...}e lo spazio precedente fornon è necessario. Anche grazie alla Josay per la <=1per <2l'ottimizzazione.


Abbastanza simile alla mia soluzione pubblicata all'incirca nello stesso minuto. Sei stato più intelligente di me a inserire l'input, ma puoi ridurlo <=1in "<2".
SylvainD,

1
Puoi fare una comprensione impostata direttamente come {...}piuttosto che set((...)). Il tuo codice deve effettivamente stampare il risultato.
xnor

@KillianDS Le regole predefinite richiedono la stampa su STDOUT o la restituzione (non valutazione REPL), e qui la stampa specificata dall'OP. Altrimenti, il modo più breve generico è usare lambdaper risparmiare sulla scrittura printo return.
xnor

1
A proposito, non lo spazio prima for; il lexer Python si divide correttamente 26for.
xnor

5

APL (15)

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

Ha bisogno che le lettere siano maiuscole e che stampino 1o 0, in questo modo:

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

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

Spiegazione:

  • ↑⍞⍞: legge due righe dalla tastiera e disponi i caratteri in una matrice N × 2.
  • ⎕A⍳: per ogni personaggio, trova in quale posizione si trova ⎕A(l'alfabeto maiuscolo).
  • -⌿: per ogni colonna, sottrarre il secondo valore dal primo valore
  • 26|: prendi il mod-26 di ciascuno di quei numeri.
  • Se le stringhe sono equivalenti a Cesare, tutti i numeri in questo elenco sono uguali, quindi:
  • ≢∪: trova il numero di valori univoci nell'elenco
  • 1=: confrontalo con 1.

Non
voterò

@AlexA .: Sto usando Dyalog APL 14. Se hai un Raspberry Pi, è gratuito; per gli studenti è anche gratuito; altrimenti è possibile scaricare una versione non registrata, che è nagware ma altrimenti identicamente funzionante a quelli reali. dyalog.com TryAPL si basa su questo, tra l'altro.
Marinus

Sarei interessato a sentire le tue opinioni su Dyalog vs. GNU APL, ngn / apl e APLX, anche se i commenti non sono proprio il luogo per una tale discussione. ;)
Alex A.,

3

J, 19 byte

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

Le lettere nella stessa posizione dovrebbero avere lo stesso caso.

Dopo aver convertito entrambe le stringhe di input nella loro rappresentazione del punto di codice con &(3&u:)confrontiamo 1con la lunghezza #del nub ~.del modulo 26 26|della differenza -delle due matrici. Il punto sarà 1se tutte le distanze di Cesare sono uguali.

Uso:

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

Provalo online qui.


3

Julia, 91 87 83 byte

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

Ungolfed + spiegazione:

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

Ciò sfrutta il fatto che le stringhe in Julia possono essere trattate come array di caratteri e che le operazioni aritmetiche possono essere eseguite sui valori dei caratteri. Le stringhe di input possono avere qualsiasi combinazione di maiuscole desiderata, purché la capitalizzazione in ciascuna posizione corrisponda tra le stringhe.


3

C99, 92 byte con errore   101 92 byte

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

Abbastanza diretto; presuppone che le parole vengano rispettivamente come primo e secondo argomento. Compilato con -std=c99.


Ciò fornisce un risultato errato per il secondo input di esempio.
Reto Koradi,

Hai ragione, l'ho perso. Fisso.
RR-

3

Javascript ( ES7 Draft ), 87 byte

Richiede che gli input siano nello stesso 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 byte

{r(fm26f%}2*=

Richiede che il primo carattere di ogni parola sia in maiuscolo, gli altri in minuscolo.

Provalo qui . ( Firefox qui .)

Peccato che le varianti APL non supportino l'aritmetica dei personaggi ...

Spiegazione

{
    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

Modifica : un'ottimizzazione fallita era scivolata nel codice golf. Ora corrisponde alla versione non golfata. (Il conteggio dei byte era corretto, però.)

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

Esegui con Perl versione 5.10 ( perl -M5.10.0o perl -E …) per say(). Versione leggermente espansa:

@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

Il codice genera 1(in verità in Perl) se le stringhe sono equivalenti a Cesare, e la stringa vuota (in falsa in Perl) se non lo sono. Se questa interpretazione è troppo lenta, devo aggiungere 2 byte per say$p+0, che stampa 1o 0.

La custodia dei caratteri deve corrispondere tra gli input.


Sulla base dei commenti sulla domanda precedente, puoi prendere input anche come argomenti della riga di comando. Puoi usare -iper prendere la seconda stringa, che la memorizzerebbe nella variabile $^I. Inoltre, l'utilizzo -Eanziché -edurante l'esecuzione dalla riga di comando sayti consentirà di utilizzarlo gratuitamente, quindi puoi utilizzarlo senza aggiungere byte. Prova a eseguire questo: perl -iteststring -E'say$^I'potresti riuscire ad accorciarlo con il -itrucco.
hmatt1,

Grazie @chilemagic, il -itrucco è pulito (e non lo sapevo!). In questo caso non credo che sia di aiuto perché $^Iè più lungo di <>.
xebtl,

@chilemagic Oh, e come in questa discussione , non ho contato i byte -M5.10.0comunque. (Ma ho menzionato l' -E
opzione

2

Matlab, 49 48 byte

Questa è stata davvero veloce. Purtroppo ottenere una stringa da stdin è piuttosto costoso.

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

Nota che, come la maggior parte se non tutte le risposte, è sensibile al maiuscolo / minuscolo.

EDIT: rasato un byte definendo una funzione anonima!


2

Prolog, 56 byte

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

Non tutte le combinazioni di casi sono supportate.

uso

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

Provalo online qui


2

C, 97 byte

#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
Sìì! Hai ripristinato l'equilibrio!
DJMcMayhem

Puoi salvare 4 caratteri se riutilizzi de dichiari ail tipo al di fuori di parametri come questo: d,r;main(int c,char**a){r;main(d,a)char**a;{
rr-

1

Scala, 57 byte

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

Poco più lungo degli altri, ed essenzialmente equivalente, ma ha un diverso stile di linguaggio!

Ho anche questa versione (56 byte):

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

Ma non so se il funzionamento di $ 1 sia una coincidenza o in base alla progettazione ...


1
È davvero strano, come x$1funziona senza xmai essere definito?
Dan Getz,

@DanGetz Sono abbastanza sicuro che sia un colpo di fortuna del compilatore. Potrei porre una domanda sullo overflow dello stack al riguardo: D
Altri,

1

Python 2, 80 byte

Prende 2 stringhe con casing simile dallo stdin separate da uno spazio:

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

Testato sui seguenti casi di test:

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

Python 2 - 241 237 188 147 byte

Accetta l'input come stringa minuscola racchiusa tra virgolette, spazio separato. Deve esserci un modo migliore ..

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)

Ungolfed (260-dispari byte)

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)

Sono sicuro che potresti allungare tutte le variabili di 1 carattere e salvare un sacco di byte. Devi anche aggiungere 4 al tuo punteggio, poiché ti aspetti 4 "s in più nel tuo input.

@Reticità Non riesco a credere di non aver abbreviato le variabili .. mossa amatoriale. Ho aggiunto 2 al conteggio dei byte, poiché non ho spiegato correttamente; input funziona come "abc cde".
Kade,

1

R, 83 84

Abbastanza simile alle altre soluzioni. Converti le stringhe in un vettore di numeri interi. Mod la differenza dei vettori per 26. Esegui un univoco sull'elenco poiché verifica che la lunghezza sia 1. Si aspetta che il caso sia lo stesso nei caratteri corrispondenti in ogni stringa.

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

Attende che vengano immesse le due stringhe

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

È possibile salvare un byte utilizzando <2anziché ==1.
Alex A.,

È possibile salvare 3 byte semplicemente 10

@AlexA. Grazie Alex mi è mancato quello ... e ora mi manca quello :)
MickyT

@Reticità: come?
Alex A.,

@Reticality Purtroppo restituirebbe 1 o maggiore di uno.
MickyT,

1

Matlab / Octave, 53 52

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

Gli input dovrebbero essere tutti dello stesso caso.

Purtroppo, Matlab non è molto bravo con l'input dell'utente. Come handle anonimo, questo potrebbe essere solo 35 byte:

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

Matlab tratta i caratteri di una stringa come un vettore di numeri. Fare sottrazione ci fa la differenza e uniqueconverte quel vettore in un vettore contenente solo valori univoci. Se esiste un solo numero, le parole sono caeser equivalenti e isscalar restituisce 1, altrimenti restituirà 0.


Oh! Un'altra voce di Matlab! Ho cercato le risposte solo dopo aver risposto a me stesso.
Oebele

appena scoperto che è possibile salvare un byte definendo input x = @ () ('', 's');
Oebele,

@Oebele Grazie! Penso che inizierò a provare altri problemi di golf in Matlab, l'ho trovato davvero divertente.
FryAmTheEggman,

Sì, lo è. Per molti problemi può essere molto conciso con le sue cose basate su matrice. Octave ha una sintassi un po 'più libera, che a volte può salvare anche qualche byte in più, come la definizione della variabile in linea.
Oebele,

1

bash, 71 48

Utilizzo del programma Unix "standard" caesar(6).

Nuova versione (con tanto aiuto da @DigitalTrauma):

read a b;seq -f"caesar %g <<<$a" 26|bash|grep $b
  • Gli input devono essere sulla stessa riga, separati da spazi
  • La custodia dei caratteri deve corrispondere tra gli input.
  • Stampa 1per vero o niente per falso.

Se è consentito l'input tramite argomenti della riga di comando, è possibile accorciarlo 39 byte :

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

Vecchia versione per il record:

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

48 byte, secondo il mio conteggio: read a b;seq -f"caesar %g <<<$a" 26|bash|grep $bil risultato è nella $?variabile incorporata, dove 0 == FALSO e 1 == VERO, secondo la semantica della shell standard.
Digital Trauma,

@DigitalTrauma Quelle sono alcune idee ingegnose! Mi piace soprattutto un seq -f | bashpo '. Il risultato $?non è valido dalla mia lettura della sfida, ma proprio come il mio codice, il tuo non produce nulla per falso e qualcosa per vero (tranne nel caso limite di due stringhe di input vuote). Ad ogni modo, sarebbe come barare usare tutto questo nella mia risposta, forse dovresti inviarne uno tuo.
xebtl,

Non ti preoccupare, ti sto offrendo i suggerimenti per giocare a golf. Se avessi voluto usarli, lo avrei già fatto :). Per quanto riguarda la verità / falsità, tendo ad interpretarlo come ciò che è vero e falso nella tua lingua - prova [ 0 == 0 ] ; echo $?e[ 0 == 1 ] ; echo $?
Digital Trauma,

1

> <> (Pesce) , 50 byte

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

Si aspetta che le lettere nella stessa posizione abbiano lo stesso caso.

Spiegazione

  • i:3b*(?v legge la prima parola nello stack con 88+0. fornendo il salto in loop
  • ~ri-&rimuove ~lo spazio di separazione dalla pila, inverte la pila r(la prima lettera sarà in alto), legge nella prima lettera della seconda parola i, calcola l'offset dalla prima lettera della prima parola -e lo memorizza nel registro& .
  • l?!^i-&:&-2d*%0)?vlegge ogni lettera successiva della seconda parola sottraendola dalla lettera corrispondente della prima parola che si trova nella parte superiore dello stack sottrae l'offset &:&-memorizzato nel registro e verifica se il risultato è 0 mod 26 2d*%. Altrimenti stampa 0 e termina0n; . c1.fornisce il salto in loop.
  • Se viene raggiunta la fine della seconda parola, il programma stampa 1 e termina 1n;.

0

KDB (Q), 35 byte

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

Spiegazione

                         "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

Test

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

allargato:

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

Potrei salvare 14 byte se mi sbarazzassi della conversione di tutto in maiuscolo, ma sento che è più completo lasciarlo.


0

Gelatina , 5 byte

Oạ/ċ2

Provalo online!

Emette un numero intero positivo per equivalente, 0 altrimenti

Come funziona

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.