Dans ce code-challenge, vous écrivez une fonction de hachage dans 140 octets 1 ou moins de code source. La fonction de hachage doit prendre une chaîne ASCII en entrée et renvoyer un entier non signé de 24 bits ([0, 2 24 -1]) en sortie.
Votre fonction de hachage sera évaluée pour chaque mot de ce grand dictionnaire anglais britannique 2 . Votre score est la quantité de mots qui partagent une valeur de hachage avec un autre mot (une collision).
Le score le plus bas gagne, les liens brisés par la première affiche.
Cas de test
Avant de soumettre, veuillez tester votre script de scoring sur l'entrée suivante:
duplicate
duplicate
duplicate
duplicate
S'il donne un score autre que 4, c'est un buggy.
Règles de clarification:
- Votre fonction de hachage doit être exécutée sur une seule chaîne, pas sur un tableau entier. En outre, votre fonction de hachage ne peut effectuer aucune autre entrée / sortie que la chaîne d'entrée et le nombre entier de sortie.
- Les fonctions de hachage intégrées ou des fonctionnalités similaires (par exemple, le cryptage pour brouiller les octets) sont interdites.
- Votre fonction de hachage doit être déterministe.
- Contrairement à la plupart des autres concours, l’optimisation spécifique de la notation est autorisée.
1 Je sais que Twitter limite les caractères au lieu d'octets, mais pour des raisons de simplicité, nous utiliserons les octets comme limite pour ce défi.
2 Modifié à partir de la propriété wbritish-huge de Debian , supprimant les mots non-ASCII.
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch's
? Qu'est-ce que ...?D=340275
mots etR=2^24
les sorties de hachage, un hachage aléatoire a desD^2/(2*R) = 3450
paires en collision attendues , dont certaines se chevauchent. DesD^3/(6*R^2) = 23
triples en collision sont prévus et un nombre négligeable de collisions plus importantes, ce qui signifie que ces triples sont probablement disjoints. Cela donne les6829
mots attendus qui partagent une valeur de hachage, ~70
en triples et le reste en paires. L’écart type étant estimé à118
, l’obtention<6200
d’un hachage aléatoire correspond en gros à un événement de 5 sigma.Réponses:
Très bien, je vais apprendre une langue de golf.
CJam, 140 octets, 3314 mots en collision
Définit un bloc (fonction anonyme). Pour tester, vous pouvez ajouter
qN%%N*N
à prendre la liste de mots séparés par une nouvelle ligne sur stdin et écrire une liste de hachages séparés par une nouvelle ligne sur stdout. Code Python équivalent:Pyth, 140 octets,
35353396 mots en collisionDéfinit une fonction nommée
y
. Pour tester, vous pouvez ajouterjmyd.z
à prendre la liste de mots séparés par une nouvelle ligne sur stdin et écrire une liste de hachages séparés par une nouvelle ligne sur stdout. Code Python équivalent:Limites théoriques
Comment pouvons-nous nous attendre à faire? Voici un graphique de x, le nombre de mots en collision, vs y, l’entropie en octets nécessaire pour obtenir au plus x mots en collision. Par exemple, le point (2835, 140) nous indique qu'une fonction aléatoire obtient au plus 2835 mots en collision avec une probabilité de 1/256 ** 140, il est donc extrêmement improbable que nous puissions jamais faire mieux que cela avec 140 octets de code.
la source
Python,
53334991Je crois que c’est le premier candidat à marquer significativement mieux qu’un oracle aléatoire.
la source
def H(s):n=int(s.encode('hex'),16);return n%...
sauve 5 octets, au cas où vous pourriez les utiliser ...2**24 == 8**8
.Python 2, 140 octets, 4266 mots en collision
Je ne voulais pas vraiment commencer par les octets non imprimables étant donné leur capacité de tweet incertaine, mais bon, je ne l'ai pas démarré. :-P
Python 2, 140 octets imprimables,
466244714362 mots en collisionInspiré par la forme de la solution de kasperd, bien sûr, mais avec l’ajout important d’une transformation affine sur l’espace module, ainsi que de paramètres totalement différents.
la source
n%(8**8-ord('…'[n%70]))
je cherchais une meilleure chaîne sans autre changement de paramètre, je n'avais réussi qu'à obtenir 4995, il semble donc que votre nouvel optimiseur a rattrapé le mien. Maintenant cela devient plus intéressant!CJam,
4125393737913677Cette approche divise le domaine et le codomaine en 110 ensembles disjoints et définit une fonction de hachage légèrement différente pour chaque paire.
Notation / Vérification
Le port suivant vers Python peut être utilisé avec l'extrait de partition officiel:
la source
h
que dans ce port Python correspond à un CJam intégré?b
(conversion de base).Python,
64466372Cette solution génère un nombre de collisions inférieur à toutes les entrées précédentes et ne nécessite que 44 des 140 octets autorisés pour le code:
la source
%(2**24-1)
, alors je pense qu'il serait bon de demander une clarification[0, 2**24-1]
que de mots en anglais, il serait mathématiquement impossible de créer un hachage où chaque valeur de cette plage était possible.CJam, 6273
XOR chaque caractère avec 49 , réduisez la chaîne résultante via x, y ↦ 245x + y , et prenez le résidu modulo 16 777 213 (le plus grand nombre premier sur 24 bits).
Notation
la source
JavaScript (ES6), 6389
La fonction de hachage (105 octets):
La fonction de scoring (NodeJS) (170 octets):
Call as
node hash.js dictionary.txt
, oùhash.js
est le script,dictionary.txt
est le fichier texte du dictionnaire (sans la nouvelle ligne) etF
est défini comme la fonction de hachage.Merci Neil d'avoir réduit de 9 octets la fonction de hachage!
la source
((...)>>>0)%(1<<24)
vous pouvez probablement utiliser(...)<<8>>>8
.i
.Mathematica, 6473
L'étape suivante ... au lieu de faire la somme des codes de caractères, nous les traitons comme les chiffres d'un nombre en base 151, avant de les prendre modulo 2 24 .
Voici un court script pour déterminer le nombre de collisions:
Je viens d'essayer systématiquement toutes les bases à
1
partir de maintenant et jusqu'à présent, la base 151 a donné le moins de collisions. Je vais essayer quelques autres pour faire baisser un peu plus le score, mais les tests sont un peu lents.la source
Javascript (ES5), 6765
C'est CRC24 réduit à 140 octets. Je pourrais jouer plus au golf mais je voulais obtenir ma réponse :)
Validateur dans node.js:
la source
Python, 340053
Un score terrible d'un algorithme terrible, cette réponse existe plus pour donner un petit script Python qui affiche le scoring.
Marquer:
la source
Python,
639063766359Peut être considéré comme une modification triviale de la réponse de Martin Büttner .
la source
[0, 2**24-1]
. La seule chose qui n'est pas autorisée est la sortie d'un nombre non compris dans cette plage, par exemple-1
ou2**24
.Python, 9310
Ouais, pas le meilleur, mais au moins c'est quelque chose. Comme on dit en crypto, n'écrivez jamais votre propre fonction de hachage .
C'est aussi exactement 140 octets de long.
la source
Matlab,
3082886206848Il construit le hachage en attribuant un nombre premier à chaque combo caractère / position ascii et en calculant leur produit pour chaque mot modulo le plus grand nombre premier inférieur à 2 ^ 24. Notez que pour le test, j'ai déplacé l'appel directement vers le premier nombre directement dans le testeur avant la boucle while et je l'ai passé dans la fonction de hachage, car il l'a accéléré d'un facteur 1 000 environ, mais cette version fonctionne correctement et est autonome. Il peut tomber en panne avec des mots de plus de 40 caractères environ.
Testeur:
la source
double
explicitement votre caractère en. Aussi, vous pouvez utilisernumel
plutôt quelength
. Je ne sais pas ce que vous feriez avec tous ces octets supplémentaires!Ruby, 9309 collisions, 107 octets
Ce n'est pas un bon candidat, mais je voulais explorer une idée différente de celle des autres participants.
Attribuez les n premiers nombres premiers aux n premières positions de la chaîne, puis additionnez tous les nombres premiers [i] ** (code ascii de la chaîne [i]), puis mod 2 ** 24-1.
la source
Java 8,
70546467Ceci est inspiré par (mais pas copié à partir de) la fonction intégrée java.lang.String.hashCode, alors n'hésitez pas à refuser selon la règle n ° 2.
Marquer:
la source
hashes
parMap<Integer, Integer> hashes = new HashMap<>()
, puis comptez le nombre de mots pour chaque hachage, vous pouvez en rendre compte correctement.Python,
699568626732Juste une simple fonction RSA. Assez boiteux, mais bat quelques réponses.
la source
C ++:
711266946483647964126339 collisions, 90 octetsJ'ai mis en œuvre un algorithme génétique naïf pour mon tableau de coefficients. Je mettrai à jour ce code car il en trouve de meilleurs. :)
Fonction de test:
la source
C #, 6251
6335Les constantes 533 et 733
889 et 155donnent le meilleur score parmi toutes celles que j'ai consultées jusqu'à présent.la source
tcl
88 octets, 6448/3233 collisions
Je vois que les gens comptent soit le nombre de mots en collision, soit le nombre de mots placés dans des seaux non vides. Je donne les deux chefs d'accusation - le premier est en fonction de la spécification du problème, et le second est ce que plus d'affiches ont rapporté.
la source
proc H w {incr h;lmap c [split $w {}] {set h [expr (2551*$h+[scan $c %c])%2**24]};set h}
... non?Python 3, 89 octets, 6534 collisions de hachage
Tous les grands nombres magiques que vous voyez ici sont des constantes de fudge.
la source
JavaScript, 121 octets,
32683250 325032446354 (3185) collisionsLes paramètres (13, 7809064, 380886, 2, 266324) sont obtenus par essai et erreur.
Encore optimisable à mon avis, et il reste encore de la place pour ajouter des paramètres supplémentaires et travailler pour une optimisation plus poussée
Vérification
3268> 3250 - Modification du 3ème paramètre de 380713 à 380560.
3250> 3244 - Modification du troisième paramètre de 380560 à 380886.
3244> 6354 - Modification du deuxième paramètre de 7809143 à 7809064 et constat que j'ai utilisé une méthode de calcul incorrecte; P
la source
Voici quelques constructions similaires, qui sont assez "semences" et permettent l'optimisation incrémentielle des paramètres. Zut, il est difficile de descendre en dessous de 6k! En supposant que le score a une moyenne de 6829 et une valeur standard de 118, j'ai également calculé la probabilité d'obtenir de tels scores bas par hasard.
Clojure A, 6019, Pr = 1: 299,5e9
Clojure B, 6021, Pr = 1: 266.0e9
Clojure C, 6148, Pr = 1: 254,0e6
Clojure, 6431, Pr = 1: 2.69e3 (quelque chose de différent)
C’était ma fonction de hachage ad-hoc d’origine, elle dispose de quatre paramètres réglables.
la source
r
est fixé). Mais mon algorithme de recherche est toujours essentiellement la force brute, et je ne suis pas sûr si le choix initial du multiplicateur der
est important ou non.f(n) % (8^8 - g(n))
.Ruby, 6473 collisions, 129 octets
La variable @p est remplie avec tous les nombres premiers inférieurs à 999.
Cela convertit les valeurs ascii en nombres premiers et leur produit modulo un nombre premier élevé. Le facteur de fudge de 179 tient compte du fait que l'algorithme d'origine était utilisé pour rechercher des anagrammes, où tous les mots qui sont des réarrangements des mêmes lettres ont le même hachage. En ajoutant le facteur dans la boucle, les anagrammes ont des codes distincts.
Je pourrais supprimer le ** 0.5 (test sqrt pour prime) au détriment de performances plus médiocres pour raccourcir le code. Je pourrais même faire exécuter le sélecteur de nombre premier dans la boucle pour supprimer neuf caractères supplémentaires, en laissant 115 octets.
Pour tester, les éléments suivants tentent de trouver la meilleure valeur pour le facteur de fudge dans la plage allant de 1 à 300. Supposons que le mot se trouve dans le répertoire / tmp:
la source
tcl
# 91 octets, 6508 collisions91 octets, 6502 collisions
L’ordinateur effectue toujours une recherche pour déterminer s’il existe une valeur causant moins de collisions que la base
147875, qui est toujours l’architecte.la source