Équivalence César

24

Deux chaînes sont "équivalentes à César" si la distance (comptage) entre les caractères correspondants est la même. Oui, j'ai inventé ce terme. Voici un exemple:

"Abc" et "Cde" sont équivalents car

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

La capitalisation ne fait aucune différence.

"Bonjour" et "Monde" ne sont pas équivalents à César car

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" et "Yzab" sont des équivalents César car

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

Vous devez écrire un programme complet qui prend deux chaînes de STDIN et imprime une valeur véridique si elles sont équivalentes à César et une valeur falsifiée si elles ne le sont pas.

Entrée valide

  • Étant donné que la capitalisation n'a pas d'importance, il est acceptable si votre programme nécessite que les entrées soient toutes en minuscules, en majuscules ou quel que soit le mélange souhaité, tant que cela est spécifié dans votre réponse.

  • L'entrée n'aura ni espaces ni ponctuation.

  • Les entrées auront la même longueur.

DJMcMayhem
la source
8
Cela aurait été bien d'autoriser l'entrée comme arguments de ligne de commande. J'allais écrire une solution C, mais la lecture de stdin nécessite un code assez long, surtout si vous n'avez pas de longueur maximale à l'avance.
Reto Koradi
@RetoKoradi Pourquoi pas? Il ne gagnera probablement pas de toute façon, car C n'est pas exactement connu pour être concis.
DJMcMayhem
D'accord, je doute que C ait jamais une chance de remporter une victoire absolue. Au mieux, je compare aux solutions qui utilisent des "vrais";) langages de programmation. Mais même là, d'autres langages ont tendance à être plus compacts, en particulier si cela implique un traitement de chaîne.
Reto Koradi
4
Chaque fois que je vois cela dans la liste des questions, il y a exactement autant de votes positifs que de réponses.
Alex A.
1
@AlexA. Je n'ai pas prêté attention au taux de vote positif / réponse jusqu'à ce que vous le signaliez. Maintenant, c'est tout ce que je remarque.
DJMcMayhem

Réponses:

10

Pyth, 9 octets

}wm=.rzGG

Les deux chaînes sont attendues en minuscules, séparées par des sauts de ligne.

Manifestation.

Comment ça marche:

.rest la fonction de traduction rotative de Pyth. Il mappe chaque élément du premier argument depuis sa première occurrence dans le deuxième argument jusqu'à l'entrée suivante dans le deuxième argument. Dans ce cas, le deuxième argument est Gl'alphabet minuscule, ce qui équivaut donc à un décalage César de 1.

Mettre un =devant la fonction le met en place. Ainsi, =.rzGaffecte le décalage César de zun à z. Notez qu'il zest initialisé à la première ligne d'entrée en Pyth.

Cette expression est utilisée dans une carte. m=.rzGGapplique cette transformation à z26 fois, une fois pour chaque élément de G, et enregistre les résultats dans une liste. Cela donne la liste de tous les changements de César possibles z.

Enfin, }wvérifie si la ligne d'entrée suivante se trouve dans cette liste.

isaacg
la source
14

CJam, 17 12 11 octets

1 octet enregistré par Dennis.

ll.m26f%)-!

Testez-le ici.

Attend que la première chaîne soit en minuscules et la seconde en majuscules. Imprime 1pour les chaînes équivalentes à César et 0autres.

Explication

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 raison pour laquelle nous avons besoin de la première chaîne en minuscules et de la seconde en majuscules est de garantir que la différence est toujours positive. Sinon, prendre le modulo pourrait retourner quelque chose de négatif et ne serait pas nécessairement unique, même pour les cordes équivalentes à César.

Martin Ender
la source
1
Si vous souhaitez que le premier mot soit en minuscules et le second en majuscules, vous pouvez utiliser 26f%pour enregistrer un octet.
Dennis
Vous pouvez utiliser la convention shell ( stackoverflow.com/questions/2933843/… ) pour la rapprocher de la réponse Pyth.
VicAche
1
@VicAche La convention acceptée est d'interpréter la vérité et la fausseté de quelque manière que votre langue l'interprète. De plus, si je supprimais le !je n'aurais pas 0 ou 1 mais un tableau vide ou non vide.
Martin Ender
9

Python2, 68 67 70 69 octets

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

Python3, 67 66 octets

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

Il est un peu difficile de ne pas jouer au golf, alors expliquez simplement les pièces:

  • zip(*raw_input().split())prend l'entrée, la divise en une liste de deux mots, en supposant que les mots sont séparés par des espaces. Après cela, chaque mot est passé en tant que paramètre de la zipfonction, à l'aide de l' *opérateur. La zipfonction créera une liste de paires de lettres, pour les lettres dans la même position.
  • (ord(y)-ord(x))%26for x,y in ... Cela transforme simplement la liste de 2 lettres en une expression génératrice des distances entre ces lettres.
  • {...} réduit cette expression à un ensemble, jetant essentiellement des doublons
  • len(...)<2 vérifie s'il ne reste qu'un seul élément dans l'ensemble (ou 0 pour les chaînes vides), ce qui signifie essentiellement que toutes les lettres ont la même distance.
  • print sort cette valeur

Merci à xnor de me le rappeler set(...)peut être remplacé par {...}et l'espace avant forn'est pas nécessaire. Grâce aussi à Josay pour l' <=1à l' <2optimisation.

KillianDS
la source
Assez similaire à ma solution publiée à peu près dans la même minute. Vous avez été plus intelligent que moi pour entrer, mais vous pouvez réduire <=1en «<2».
SylvainD
1
Vous pouvez faire une compréhension d'ensemble directement {...}plutôt que set((...)). Votre code doit réellement imprimer le résultat.
xnor
@KillianDS Les règles par défaut requièrent l'impression sur STDOUT ou le retour (pas d'évaluation REPL), et ici l'impression spécifiée OP. Sinon, le moyen le plus court générique est d'utiliser lambdapour économiser sur l'écriture printou return.
xnor
1
Soit dit en passant, vous n'avez pas l'espace avant for; le lexer Python se divise correctement 26for.
xnor
5

APL (15)

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

Il a besoin que les lettres soient en majuscules et imprime soit 1ou 0, comme ceci:

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

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

Explication:

  • ↑⍞⍞: lisez deux lignes sur le clavier et organisez les caractères dans une matrice N × 2.
  • ⎕A⍳: pour chaque caractère, trouvez à quelle position il se trouve ⎕A(l'alphabet majuscule).
  • -⌿: pour chaque colonne, soustrayez la deuxième valeur de la première valeur
  • 26|: prenez le mod-26 de chacun de ces nombres.
  • Si les chaînes sont équivalentes à César, tous les nombres de cette liste sont maintenant égaux, donc:
  • ≢∪: trouver le nombre de valeurs uniques dans la liste
  • 1=: comparer cela à 1.
marinus
la source
Je ne voterai jamais APL :)
orlp
@AlexA .: J'utilise Dyalog APL 14. Si vous avez un Raspberry Pi, c'est gratuit; pour les étudiants, c'est aussi gratuit; sinon, vous pouvez télécharger une version non enregistrée, qui est un nagware mais sinon fonctionnellement identique aux vraies. dyalog.com TryAPL est basé sur cela, soit dit en passant.
marinus
Je serais intéressé d'entendre vos réflexions sur Dyalog vs GNU APL, ngn / apl et APLX, bien que les commentaires ne soient pas vraiment le lieu d'une telle discussion. ;)
Alex A.
3

J, 19 octets

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

Les lettres à la même position devraient avoir le même cas.

Après avoir converti les deux chaînes d'entrée en leur représentation de point de code avec &(3&u:)nous comparons 1à la longueur #du nœud ~.du modulo 26 26|de la différence -des deux tableaux. Le nœud sera 1si toutes les distances de César sont les mêmes.

Usage:

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

Essayez-le en ligne ici.

randomra
la source
3

Julia, 91 87 83 octets

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

Non golfé + explication:

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

Cela tire parti du fait que les chaînes de Julia peuvent être traitées comme des tableaux de caractères et que des opérations arithmétiques peuvent être effectuées sur des valeurs de caractères. Les chaînes d'entrée peuvent avoir n'importe quelle combinaison de majuscules que vous souhaitez, tant que la capitalisation à chaque position correspond entre les chaînes.

Alex A.
la source
3

C99, 92 octets avec bug   101 92 octets

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

Assez simple; suppose que les mots viennent respectivement comme premier et deuxième arguments. Compilé avec -std=c99.

rr-
la source
Cela donne le mauvais résultat pour la deuxième entrée d'échantillon.
Reto Koradi
Tu as raison, je l'ai raté. Fixé.
rr
3

Javascript ( ES7 Draft ), 87 octets

Nécessite que les entrées soient identiques.

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

nderscore
la source
2

CJam, 13 octets

{r(fm26f%}2*=

Il faut que le premier caractère de chaque mot soit en majuscule, les autres en minuscule.

Essayez-le ici . ( Firefox ici .)

Dommage que les variantes APL ne prennent pas en charge l'arithmétique des personnages ...

Explication

{
    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.
jimmy23013
la source
2

Perl, 80

Edit : une optimisation échouée s'était glissée dans le code du golf. Maintenant, il correspond à la version non golfée. (Le nombre d'octets était correct, cependant.)

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

Exécutez avec Perl version 5.10 ( perl -M5.10.0ou perl -E …) pour say(). Version légèrement élargie:

@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

Le code 1génère (véridique en Perl) si les chaînes sont équivalentes à César et la chaîne vide (fausse en Perl) si elles ne le sont pas. Si c'est une interprétation trop lâche, je dois ajouter 2 octets poursay$p+0 , qui imprime 1ou 0.

La casse des caractères doit correspondre entre les entrées.

xebtl
la source
Sur la base des commentaires sur la question ci-dessus, vous pouvez également prendre l'entrée comme arguments de ligne de commande. Vous pouvez utiliser -ipour prendre la deuxième chaîne, qui la stockera dans la variable $^I. En outre, utiliser -Eau lieu de -elors de l'exécution sur la ligne de commande vous permettra d'obtenir saygratuitement, vous pouvez donc l'utiliser sans ajouter d'octets. Essayez d'exécuter ceci: perl -iteststring -E'say$^I'vous pourriez être en mesure de raccourcir cela avec l' -iastuce.
hmatt1
Merci @chilemagic, l' -iastuce est soignée (et je ne le savais pas!). Dans ce cas, je ne pense pas que cela aide car $^Iest plus long que <>.
xebtl
@chilemagic Oh, et selon cette discussion , je n'ai de -M5.10.0toute façon pas compté les octets . (Mais j'ai mentionné le -Echangement dans le montage)
xebtl
2

Matlab, 49 48 octets

Ce fut très rapide. Malheureusement, obtenir une chaîne de stdin est assez cher.

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

Notez qu'il est, comme la plupart des réponses sinon toutes, sensible à la casse.

EDIT: rasé d'un octet en définissant une fonction anonyme!

Oebele
la source
2

Prolog, 56 octets

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

Toutes les combinaisons de cas ne sont pas prises en charge.

usage

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

Essayez-le en ligne ici

Persitz
la source
2

C, 97 octets

#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");}
Reto Koradi
la source
1
Yay! Vous avez rétabli l'équilibre!
DJMcMayhem
Vous pouvez enregistrer 4 caractères si vous réutilisez det déclarez ale type de paramètres extérieurs comme celui-ci: d,r;main(int c,char**a){r;main(d,a)char**a;{
rr-
1

Scala, 57 octets

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

Un peu plus long que les autres, et essentiellement équivalent, mais il est dans un style de langue différent!

J'ai également cette version (56 octets):

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

Mais je ne sais pas si le fonctionnement de x $ 1 est une coïncidence ou par conception ...

Autres
la source
1
C'est vraiment bizarre, comment ça x$1marche sans xjamais être défini?
Dan Getz
@ DanGetz Je suis presque sûr que c'est un coup de chance du compilateur. Je peux poser une question sur le débordement de pile à ce sujet: D
Autres
1

Python 2, 80 octets

Prend 2 chaînes similaires de stdin séparées par un espace:

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

Testé sur les cas de test suivants:

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)
SylvainD
la source
1

Python 2 - 241 237 188 147 octets

Prend l'entrée sous forme de chaîne minuscule entre guillemets, séparée par des espaces. Il doit y avoir une meilleure façon..

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)

Non golfé (260 octets impairs)

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)
Kade
la source
Je suis sûr que vous pourriez faire toutes les variables 1 caractère de long et enregistrer un tas d'octets. Vous devez également ajouter 4 à votre score, car vous attendez 4 "s supplémentaires dans votre entrée.
@Reticsity Je ne peux pas croire que je n'ai pas raccourci les variables .. déménagement amateur. J'ai ajouté 2 au nombre d'octets, car je ne l'ai pas expliqué correctement; l'entrée fonctionne comme "abc cde".
Kade
1

R, 83 84

À peu près la même chose que les autres solutions. Convertissez les chaînes en un vecteur d'entiers. Modifiez la différence des vecteurs par 26. Faites un unique sur la liste car vérifiez que la longueur est 1. Il s'attend à ce que la casse soit la même en caractères correspondants dans chaque chaîne.

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

Il attend que les deux chaînes soient entrées

> 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
>
MickyT
la source
Vous pouvez enregistrer un octet en utilisant <2plutôt que ==1.
Alex A.
Vous pouvez économiser 3 octets en sortant simplement 1ou0
@AlexA. Merci Alex, j'ai raté celui-là ... et maintenant je le manque :)
MickyT
@Reticsity: Comment?
Alex A.
@Rhicity Malheureusement, il retournerait 1 ou plus d'un.
MickyT
1

Matlab / Octave, 53 52

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

Les entrées doivent toutes être du même cas.

Malheureusement, Matlab n'est pas très bon avec les commentaires des utilisateurs. En tant que descripteur anonyme, cela ne peut représenter que 35 octets:

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

Matlab traite les caractères d'une chaîne comme un vecteur de nombres. Faire la soustraction nous fait leur différence, etunique convertit ce vecteur en un vecteur contenant uniquement des valeurs uniques. S'il n'y a qu'un seul nombre, les mots sont équivalents céser et isscalar renvoie 1, sinon il retournera 0.

FryAmTheEggman
la source
Oh! Une autre entrée Matlab! Je n'ai regardé les réponses qu'après m'être répondu.
Oebele
vient de découvrir que vous pouvez enregistrer un octet en définissant x = @ () input ('', 's');
Oebele
@Oebele Merci! Je pense que je vais commencer à essayer plus de problèmes de golf dans Matlab, je l'ai trouvé plutôt amusant.
FryAmTheEggman
Oui, ça l'est. Pour de nombreux problèmes, il peut être très concis avec ses éléments matriciels. Octave a une syntaxe un peu plus libre, ce qui peut parfois également économiser quelques octets supplémentaires, comme la définition de variable en ligne.
Oebele
1

bash, 71 48

Utilisation du programme Unix «standard» caesar(6).

Nouvelle version (avec beaucoup d'aide de @DigitalTrauma):

read a b;seq -f"caesar %g <<<$a" 26|bash|grep $b
  • Les entrées doivent être sur la même ligne, séparées par des espaces
  • La casse des caractères doit correspondre entre les entrées.
  • Imprime 1pour vrai ou rien pour faux.

Si l'entrée via des arguments de ligne de commande est autorisée, elle peut être raccourcie à 39 octets :

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

Ancienne version pour le dossier:

 read a b;for i in `seq 26`;do [ `echo $a|caesar $i` = $b ]&&echo 1;done
xebtl
la source
48 octets, d'après mon compte: read a b;seq -f"caesar %g <<<$a" 26|bash|grep $bLe résultat est dans la $?variable intégrée, où 0 == FAUX et 1 == VRAI, selon la sémantique standard du shell.
Digital Trauma
@DigitalTrauma Ce sont des idées astucieuses! J'aime particulièrement le seq -f | bashmorceau. Le résultat $?n'est pas valide par ma lecture du défi, mais tout comme mon code, le vôtre ne produit rien pour faux et quelque chose pour vrai (sauf dans le cas limite de deux chaînes d'entrée vides). Quoi qu'il en soit, ce serait comme tricher d'utiliser tout cela dans ma réponse, peut-être devriez-vous soumettre le vôtre.
xebtl
Ne vous inquiétez pas - je vous offre les conseils de golf à utiliser. Si je voulais les utiliser, je l'aurais déjà fait :). En ce qui concerne la vérité / falsey, j'ai tendance à l'interpréter comme ce qui est vrai et faux dans la langue que vous donnez - essayez [ 0 == 0 ] ; echo $?et[ 0 == 1 ] ; echo $?
Digital Trauma
1

> <> (Poisson) , 50 octets

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

S'attend à ce que les lettres au même endroit aient la même casse.

Explication

  • i:3b*(?vlit le premier mot dans la pile en 88+0.fournissant le saut en boucle
  • ~ri-&supprime ~l'espace de séparation de la pile, inverse la pile r(la première lettre sera en haut), lit la première lettre du deuxième mot i, calcule le décalage par rapport à la première lettre du premier mot -et le stocke dans le registre &.
  • l?!^i-&:&-2d*%0)?vlit chaque lettre suivante du deuxième mot en la soustrayant de la lettre correspondante du premier mot qui est en haut de la pile soustrait l'offset &:&-stocké dans le registre et vérifie si le résultat est 0 mod 26 2d*%. Sinon, imprime 0 et se termine 0n;. c1.fournit le saut en boucle.
  • S'il est atteint à la fin du deuxième mot, le programme imprime 1 et se termine 1n;.
randomra
la source
0

KDB (Q), 35 octets

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

Explication

                         "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

Tester

q){0=sum(1_-':)mod[;26](-)."i"$(x;y)}["abcd";"yzab"]
1b
WooiKent Lee
la source
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();}}

étendu:

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

Je pourrais économiser 14 octets si je me débarrassais de tout convertir en majuscules, mais j'ai l'impression qu'il est plus complet de le laisser.

Jack Ammo
la source
0

Gelée , 5 octets

Oạ/ċ2

Essayez-le en ligne!

Génère un entier positif pour l'équivalent, 0 sinon

Comment ça marche

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
caird coinheringaahing
la source