La distance de Hamming entre deux chaînes de longueur égale est le nombre de positions auxquelles les symboles correspondants sont différents.
Soit P
une chaîne binaire de longueur n
et T
une chaîne binaire de longueur 2n-1
. Nous pouvons calculer les n
distances de Hamming entre P
et chaque n
sous-chaîne de longueur T
dans l'ordre de gauche à droite et les mettre dans un tableau (ou une liste).
Exemple de séquence de distance de Hamming
Soit P = 101
et T = 01100
. La séquence des distances de Hamming que vous obtenez de cette paire est 2,2,1
.
Tâche
Pour augmenter à n
partir de n=1
, considérez toutes les paires possibles de chaînes binaires P
de longueur n
et T
de longueur 2n-1
. Il existe de 2**(n+2n-1)
telles paires et donc de nombreuses séquences de distances de Hamming. Cependant, bon nombre de ces séquences seront identiques. La tâche consiste à trouver combien sont distincts pour chacun n
.
Votre code doit afficher un nombre par valeur de n
.
But
Votre score est le plus élevé n
atteint par votre code sur ma machine en 5 minutes. Le timing est pour le temps de fonctionnement total, pas le temps juste pour cela n
.
Qui gagne
La personne avec le score le plus élevé gagne. Si deux personnes ou plus se retrouvent avec le même score, c'est la première réponse qui l'emporte.
Exemples de réponses
Pour n
de 1
aux 8
réponses optimales sont 2, 9, 48, 297, 2040, 15425, 125232, 1070553
.
Langues et bibliothèques
Vous pouvez utiliser toutes les langues et bibliothèques disponibles que vous aimez. Dans la mesure du possible, il serait bon de pouvoir exécuter votre code, veuillez donc inclure une explication complète sur la façon d'exécuter / compiler votre code sous Linux si possible.
Ma machine Les horaires seront exécutés sur ma machine 64 bits. Il s'agit d'une installation Ubuntu standard avec 8 Go de RAM, processeur AMD FX-8350 à huit cœurs et Radeon HD 4250. Cela signifie également que je dois pouvoir exécuter votre code.
Réponses principales
- 11 en C ++ par feersum. 25 secondes.
- 11 en C ++ par Andrew Epstein. 176 secondes.
- 10 en Javascript par Neil. 54 secondes.
- 9 à Haskell par nimi. 4 minutes et 59 secondes.
- 8 en Javascript par fəˈnɛtɪk. 10 secondes.
fastest-code
laisse plus d'espace pour les optimisations grâce aux optimisations au niveau du code et à un bon algorithme. Je pense donc quefaster-code
c'est mieux quefaster-algorithm
.Réponses:
C ++ 11 (devrait atteindre 11 ou 12)
Pour le moment, il s'agit d'un seul thread.
Compiler:
la source
feersum.cpp:111:61: warning: shifting a negative signed value is undefined [-Wshift-negative-value] int middle = int(s >> npre * MAX_N_BITS) & ~(~0 << MAX_N_BITS);
Haskell, score 9
Compilez avec
-O3
. Il faut 6min35s sur mon matériel d'ordinateur portable de 6 ans pour fonctionnern=9
, donc c'est peut-être moins de 5min sur le matériel de référence.la source
JavaScript, marquez 10
Explication: le calcul
n=10
est difficile car il y a plus de deux milliards de paires et plus de 26 milliards de séquences potentielles. Afin d'accélérer les choses, j'ai divisé le calcul en 121 cases. Parce que les séquences sont invariantes sous complément binaire, je peux supposer sans perte de généralité que le bit central deT
est nul. Cela signifie que je peux déterminer les premier et dernier éléments de la séquence indépendamment des bits supérieurn-1
et inférieurn-1
deT
. Chaque bac correspond à une paire différente de premier et dernier éléments; Je passe ensuite en revue tous les ensembles possibles de bits supérieurs et inférieurs qui correspondent à chaque groupe et calcule les éléments restants de la séquence, en comptant enfin les séquences uniques pour chaque groupe. Il reste alors à totaliser l'ensemble des 121 bacs. Prenant à l'origine 45 heures, cela s'est terminé en un peu moins de trois minutes et demie sur mon AMD FX-8120. Edit: Merci à @ChristianSievers pour une accélération de 50%. Sortie complète:la source
n
comme paramètre. (Désolé pour le mauvais choix de nom de paramètre là-bas.)n=1
(je ne sais pas pourquoi il se bloque).C ++, score
1011Il s'agit d'une traduction de la réponse de @ Neil en C ++, avec une simple parallélisation.
n=9
se termine en 0,4 seconde,n=10
en 4,5 secondes etn=11
en environ 1 minute sur mon Macbook Pro 2015. Merci aussi à @ChristianSievers. En raison de ses commentaires sur la réponse de @ Neil, j'ai remarqué quelques symétries supplémentaires. Des 121 seaux d'origine (pourn=10
) à 66 seaux en tenant compte de l'inversion, je suis descendu à seulement 21 seaux.Utilisez le script suivant pour exécuter le code:
Le résultat était le suivant: (Le format est
M: result, seconds
)n=12
a pris 42 minutes pour calculer sur un seul thread et a donné un résultat de 7368225813.la source
sudo apt-get install libiomp-dev
.__builtin_popcount
.__builtin_popcount
dans un contexte constexpr. Je pourrais aller avec l'implémentation naïve et cela n'affecterait pas le temps d'exécution.JavaScript 2,9,48,297,2040,15425,125232,1070553,9530752
Exécuter dans la console:
Essayez-le en ligne!
Ou en tant qu'extrait de pile:
Afficher l'extrait de code
Le code préinitialise le tableau pour accélérer l'ajout de 1 au tableau
Le code trouve toutes les séquences de distance de hamming et les traite comme une base numérique (entrée + 1), les utilise pour placer des 1 dans un tableau. En conséquence, cela génère un tableau avec les n 1s où n est le nombre de séquences uniques de distance de brouillage. Enfin, le nombre de 1 est compté à l'aide de array.reduce () pour additionner toutes les valeurs du tableau.
Ce code ne pourra pas s'exécuter pour une entrée de 10 car il atteint les limites de la mémoire
Ce code s'exécute en temps O (2 ^ 2n) car c'est le nombre d'éléments qu'il génère.
la source
n = 9
prend 5 minutes et 30 secondes pour moi en utilisant node.js est donc trop lent.n = 8
initialement pris 24 secondes sur mon PC, mais j'ai pu optimiser le code, ce qui an = 8
pris 6 secondes. J'ai ensuite essayén = 9
et cela a pris 100 secondes.