Ce code de golf a été inspiré par le récent article du Daily WTF Vous ne pouvez pas gérer le vrai! , qui comporte une comparaison de chaînes écrite comme suit:
String yes = "YES";
if ((delay.hashCode()) == yes.hashCode())
Imaginez le problème que l’équipe de Steve aurait eu si la String.hashCode
méthode de Java avait été implémentée de cette manière "YES".hashCode() == "NO".hashCode()
. Donc, le défi que je propose ici est:
Ecrivez, dans le moins de caractères possible, une fonction de hachage (je l'appellerai
h
) avec un paramètre de chaîne et une valeur de retour entière, telle qu'elleh("YES")
soit égale àh("NO")
.
Bien sûr, il serait trivial de le faire avec une fonction comme def h(s): return 0
, ce qui crée une collision de hachage pour chaque chaîne. Pour rendre ce défi plus intéressant, vous devez respecter la règle supplémentaire suivante:
Parmi les autres 18 277 chaînes possibles composé de trois lettres ou moins ASCII (majuscules
^[A-Z]{0,3}$
), il doit y avoir aucune collision de hachage.
Clarification (soulignée par Heiko Oberdiek): La chaîne de saisie peut contenir des caractères autres que A-Z
, et votre code doit être en mesure de hacher des chaînes arbitraires. (Vous pouvez toutefois supposer que l'entrée est une chaîne de caractères plutôt qu'un pointeur null ou un objet d'un autre type de données.) Toutefois, peu importe la valeur de retour pour les chaînes qui ne correspondent pas ^[A-Z]{0,3}$
, tant que c'est un entier.
De plus, pour brouiller l’intention de cette fonction:
Votre code ne doit contenir aucune des lettres "Y", "E", "S", "N" ou "O" (en majuscules ou minuscules) dans les littéraux de caractères ou de chaînes.
Bien sûr, cette restriction ne concerne pas les mots clés du langage, donc else
, return
, etc. sont très bien.
YESNO
pour vérifier cette exception spécifique n'aide en rien .Réponses:
GolfScript: 19 caractères (24 caractères pour la fonction nommée)
Ceci est le corps de la fonction. L'attribuer à une fonction nommée
h
nécessite cinq caractères supplémentaires:(Le dernier point-virgule peut être omis, si cela ne vous dérange pas de laisser une copie du code sur la pile.)
Le cœur de la fonction de hachage est le
26base
calcul de la somme (26 n - k · a k ; k = 1 .. n ), où n est le nombre de caractères de l'entrée et a k le code ASCII de la k- ème caractère d'entrée. Pour les entrées composées de lettres ASCII majuscules, il s'agit d'une fonction de hachage sans collision. Le reste du code compare le résultat à 2107 (le code de hachage deNO
) et, s’ils sont égaux, ajoute 59934 pour obtenir 2701 + 59934 = 62041, le code de hachage deYES
.Par exemple, voir cette démonstration en ligne avec des cas de test.
la source
h('DXP') == h('KK') == 65884
.lambda w:sum(ord(c)*26**i for i,c in enumerate(reversed(w*9)))%102983
) :Python 32 bits 2.x (19)
RSA utilise un module semi-prime, ce qui le sécurise. En utiliser un avec mon algorithme de hachage devrait certainement le rendre encore meilleur! 1
Ceci est une fonction mathématique pure, fonctionne pour toutes les chaînes (enfer, fonctionne pour tout objet Python hachage), et ne contient pas de conditional ou de casse spéciale! Python 32 bits peut généralement être appelé comme
python-32
sur la plupart des systèmes sur lesquels les deux sont installés 2 .J'ai testé cela et il renvoie 18 278 valeurs différentes pour les 18 279 chaînes de 3 lettres ou moins en majuscules. L'attribution de cette fonction à une fonction nécessite 11 octets supplémentaires:
et
h('YES') == h('NO') == 188338253
.Python 2.x 64 bits (19)
Même affaire que ci-dessus.
Pour arriver à ces chiffres, un peu de calcul modulaire a été utilisé. Je cherchais une fonction
f
et un modulen
tels quehash(f('YES')) % n == hash(f('NO')) % n
. Ceci équivaut à un test quin
divised = hash(f('YES')) - hash(f('NO'))
, c'est-à-dire qu'il suffit de vérifier les facteurs ded
pour des valeurs appropriées den
.L’idéal
n
est d’environ 20000 ** 2 pour réduire les risques de collision avec un paradoxe d’anniversaire. Trouver une solution adaptéen
s'avère être un peu un essai et une erreur, en jouant avec tous les facteurs ded
(il n'y a généralement pas beaucoup) et des choix différents pour la fonctionf
. Notez cependant que les essais et les erreurs ne sont nécessaires que parce que je voulais faire len
plus petit possible (pour le golf). Si ce n'était pas une exigence, je pourrais simplement choisird
mon module, qui est généralement suffisamment grand.Notez également que vous ne pouvez pas tirer cette astuce en utilisant simplement
f(s) = s
(la fonction identité) car le caractère le plus à droite de la chaîne a essentiellement une relation linéaire (en fait uneXOR
relation) avec le hachage final (les autres caractères contribuent de manière beaucoup plus non linéaire). ). La répétition de la chaîne garantit donc que les différences entre les chaînes sont amplifiées pour éliminer l’effet de ne changer que le caractère le plus à droite.1 Ceci est un non-sens évident.
2 Le hachage de chaîne Python dépend de la version majeure (2 vs 3) et du nombre de bits (32 bits contre 64 bits). Cela ne dépend pas de la plate-forme AFAIK.
la source
hash('YES'*9)
a34876679
comme un facteur, touthash('NO'*9)
a34876679+537105043
un facteur. Mais comment avez-vous su que537105043
c'était un bon module? c'est-à-dire qu'il n'a pas fait d'autres collisions?Perl,
534940 octetsTester:
Les valeurs de hachage pour
YES
etNO
sont identiques et il y a 18279 chaînes^[A-Z]{0,3}$
libres de collision, à l'exception de la seule collision pourYES
etNO
.Ungolfed:
Ancienne version, 49 octets
Comme le nouvel algorithme est légèrement différent, je conserve l'ancienne version.
Tester:
Ungolfed:
Modifications:
"\0"
comme octet de remplissage enregistre 4 octets par rapport à$"
.la source
5457241
et20047
venir? Comment calculez-vous ces chiffres? Merci d'avance.YES
dans l'hex est594553
. 0x594553 = 5850451.NO
en hexadécimal est4e4f
. 0x4e4f = 20047.Python: 63
Une solution incroyablement boiteuse:
Cela fonctionne en interprétant les chaînes alphanumériques comme des nombres en base 36 et en renvoyant 0 pour tout le reste. Il existe un cas particulier explicite pour vérifier une valeur de retour de 852 (NO) et 44596 (YES) à la place.
la source
try:
et la troisième ligne entière. Vous pouvez également économiser quelques bits en plaçant chaque ligne logique sur la même ligne, séparées par des points-virgules (def h(s):r=int(s,36);return(r,44596)[r==852]
)Pure Bash, 29 octets (corps de la fonction)
Ceci traite simplement la chaîne d'entrée comme un nombre de base 36 et la convertit en décimale, puis traite le
NO
cas spécial .Sortie:
la source
Ruby, 51 octets
code de test:
sortie:
la source
Javascript ( ES6 ) 54 octets
la source
Java -
9477Déroulé:
Narrative - pour
f(s) = BigInteger(s.getBytes())
:f("YES") xor f("NO") = 5835548
f("YES") xor 5835548 = f("NO")
f("YES") - (f("YES") xor 5835548) = f("NO") - (f("NO") xor 5835548)
j'ai raison?la source
CJam, 15 octets
Fonctionne comme la solution GolfScript ci-dessous. Essayez-le en ligne.
GolfScript, 17 octets
Cette approche s'appuie sur les réponses de Nneonneo et Ilmari Karonen .
Comment ça fonctionne
Choisir un algorithme
Nous commençons par
{b base}:h
, c'est-à-dire que la chaîne d'entrée est considérée comme un nombre base-b. Tant queb > 25
,h
est inyective.Nous obtenons une collision pour les chaînes "OUI" et "NON" si nous modifions
h
de la manière suivante:,{x base n}:h
oùn
est un diviseur de"YES" h "NO" h -
.Malheureusement, cela signifie que nous aurons également une collision pour, par exemple,
YET
etNP
. Pour éviter cela, nous devons modifier le nombre base-b de manière non linéaire avant de prendre le module.Dans GolfScript, le moyen le plus simple d’atteindre cet objectif consiste à multiplier le nombre base-b par lui-même (c’est-à-dire de le mettre au carré).
h
est maintenant{base b .* n %}:h
.Tout ce qui reste à faire est de trouver des valeurs appropriées pour
b
etn
. Nous pouvons accomplir cela par la force brute:Les valeurs les plus courtes possibles pour
b n
sont:Essai
la source
JavaScript (ES6) - 38 caractères (corps de la fonction 33 caractères)
Cas de test:
Explication:
Tout d’abord, permettez-moi de vous présenter
NaN
- "Pas un nombre" - en JavaScript. C'est un numéro:Juste comme:
Sa propriété particulière est qu'il ne s'égale jamais . Ma fonction retourne
1
si la chaîne estYES
ouNO
, etNaN
pour toute autre chaîne.Donc, cela n'enfreint pas les règles, car il n'y aurait aucune collision de hachage pour aucune autre chaîne;) (
NaN !== NaN
montré ci-dessus dans les cas de test).Et mon rêve devient réalité: battre Bash, Perl et Ruby en longueur de code!
Code non-golfé:
Si cette valeur est
"WUVT"
ou"Tk8="
, retournez1
. Sinon retource qui serait
NaN
.la source
^\d+$
. Et JS traiteNaN
comme un nombre. Vous pouvez le multiplier par un nombre, ajouter, diviser, soustraire comme avec des nombres. C'est une propriété spéciale de JavaScript. Il n'y a pas de mal à l'utiliser. C'est ce qu'on appelle la flexion des règles ;)Object.is()
et prétendre que c'est toujours une collision…==
) à des fins de comparaison, ce qui garantira qu'aucune collision de hachage ne se produit pour une chaîne autre que "YES" ou "NO".NaN
ne compte pas comme collision semble pas cher, cette solution a des collisions avec des chaînesNA
parNP
et àYEQ
traversYET
Python 92
La fonction de hachage concatène les valeurs ordinales des caractères ASCII. L'instruction print veille à la collision des deux entrées souhaitées.
la source
ECMAScript 6 (30 octets)
J'ai essayé d'éviter les mots-clés d'attribution, de retour et de fonction de variable, et cela semble être un excellent moyen d'éviter tout ce qui est absurde (cela ressemble aussi à de la programmation fonctionnelle, en quelque sorte). Contrairement à d'autres solutions, elle ne dépend pas de
btoa
ouatob
, ce qui n'est pas ECMAScript 6, mais HTML5.0+
est nécessaire pour pouvoir analyser des chaînes arbitraires.la source
a=>parseInt(0+a,36)-852||43744
Java - 45 (ou 62?)
Je ne sais pas comment évaluer équitablement compte tenu de ce qui est nécessaire pour exécuter un programme en Java. Dois-je inclure la définition de la fonction? N'hésitez pas à modifier et à ajuster mon score de manière appropriée. Actuellement, je marque de la même manière que la réponse @OldCurmudgeon. Ajoutez 17
int h(String t){}
si nécessaire:Ungolfed avec harnais de test:
la source
Et le perdant est ...
Convoyeur, 145 caractères
Fondamentalement, ce programme est en quelque sorte basé sur les caractères. Après cela, il vérifie si le hachage est égal à 12999 (le code de hachage de OUI) et si oui, affiche 404 (le hachage de NON), sinon il imprimera simplement le hachage.
Conveyor est un langage que j'ai créé et qui est actuellement en phase bêta, mais un interprète ainsi que quelques exemples et le code source sont disponibles à l' adresse suivante : https://github.com/loovjo/Conveyor.
la source
C # 4.5 (112 octets)
Version de travail (?) De la tentative de undergroundmonorail, en C #. Concatte les octets de la chaîne en un entier de 32 bits (ne fonctionne que jusqu'à 4 caractères), puis OR le résultat par rapport au résultat pour "YES" et "NO" respectivement, puis les OR ensemble.
Bien que cela puisse entrer en collision à un moment donné, cela ne devrait pas arriver pour aucun ^ [AZ] {2,3} $ autre que "OUI" et "NON".
la source
Pas de commentaire - 31 (contenu de la fonction: 26)
Solution assez simple. ;) Fonctionne pour toutes les chaînes UTF-8.
EXPLICATION:
'
est, évidemment, la fonction. Tout d'abord, il vérifie si*
(c'est l'entrée) est égal à|,,|+|"#|
(|NO|
). Si c'est le cas, il retourne|, |+|-%3|
(|YES|
) - sinon, il retourne simplement*
.la source
C 54
Convertissez la chaîne en entier - "NON" et multipliez-la par la même valeur + "NON" - "OUI" pour obtenir 0 pour "NON" et "OUI" et différent de zéro pour toute autre chaîne de la plage spécifiée.
Toutes les valeurs sur la machine Windows 7 s'il y a des problèmes finaux.
la source
Stax ,
12 à11 octetsExécuter et déboguer
Traduit l'entrée en base 36, soustrait 852, puis remplace 0 par 43744. C'est l'un des meilleurs solutions de Konrad .
la source
CoffeeScript - 36
Devrait revenir
1
pourYES
etNO
, etatob
tout ce que le non- sens brouillé produit pour tout le reste n'est pas une chaîne base64.L'équivalent JavaScript ( pas le code JS du compilateur CS):
la source
_
lorsque l'entrée n'est pas "OUI" ou "NON".Voici un super boiteux. SO LAME, IL NE FONCTIONNE PAS MÊME
Python 2.7 - 79 octetsNous obtenons d’abord la somme de (la valeur ascii de chaque caractère) * 100 ^ (la position de ce caractère dans la chaîne). Ensuite, nous multiplions (ce résultat - 7978) et (ce résultat - 836989) pour obtenir notre réponse finale. 7978 et 836989 sont les résultats pour "OUI" et "NON" du premier bit, donc pour OUI et NON, nous multiplions par 0.
Cela ne devrait pas avoir de collisions? Je n'ai pas le goût de tester contre 18 000 contre-exemples possibles, mais en cas de collision non intentionnelle, je peux ajouter un autre 0
100
et il ne devrait y avoir aucune collision.Déçu de ne pouvoir utiliser a
lambda
pour cela, mais comme je ne voulais pas faire le calcul complet deux fois, je devais le sauvegarder dans une variable.S'il vous plaît ne laissez pas cela gagner. C'est super nul et je ne le mérite pas.
la source