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
.
Définition de proximité
Considérons maintenant deux de ces séquences de distances de Hamming. Dites x = (0, 2, 2, 3, 0)
et y = (2, 1, 4, 4, 2)
comme exemples. Nous disons cela x
et y
sommes close
si y <= x <= 2*y
ou si x <= y <= 2*x
. Ici, la multiplication scalaire et l'inégalité sont prises élément par élément. C'est - à - dire pour deux séquences A
et B
, A <= B iff A[i] <= B[i]
pour tous les indices i
.
Notez que les séquences de distances de Hamming forment un ordre partiel sous cette façon de les comparer. En d'autres termes, de nombreuses paires de séquences ne sont ni supérieures ni égales ni inférieures ou égales les unes aux autres. Par exemple (1,2)
et (2,1)
.
Donc, en utilisant l'exemple ci-dessus, (0, 2, 2, 3, 0) <= 2*(2, 1, 4, 4, 2) = (4, 2, 8, 8, 4)
mais (0, 2, 2, 3, 0)
n'est pas plus grand que (2, 1, 4, 4, 2)
. N'est (2, 1, 4, 4, 2)
pas non plus inférieur ou égal à 2*(0, 2, 2, 3, 0) = (0, 4, 4, 6, 0)
. En conséquence x
et y
ne sont pas proches les uns des autres.
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 la taille du plus grand ensemble de séquences de distance de Hamming afin qu'il n'y ait pas deux séquences proches l'une de l'autre.
Votre code doit afficher un nombre par valeur de n
.
But
Votre score est globalement le plus élevé n
atteint par votre code sur ma machine en 5 minutes (mais lisez la suite). Le timing est pour le temps de fonctionnement total, pas le temps juste pour cela n
.
Afin de donner des scores pour les réponses non optimales, parce que trouver des réponses optimales est probablement difficile, nous aurons besoin d'un système de notation légèrement subtil. Votre score est la valeur la plus élevée n
pour laquelle personne d'autre n'a publié de réponse correcte plus élevée pour toute taille inférieure ou égale à celle-ci. Par exemple, si vous sortez 2, 4, 21
et que quelqu'un d'autre sort, 2, 5, 15
vous ne marquerez 1
que si quelqu'un d'autre a une meilleure réponse pour n = 2
. Si vous produisez, 2, 5, 21
vous obtiendrez un score, 3
peu importe ce que quelqu'un d'autre produit car ces réponses sont toutes optimales. De toute évidence, si vous avez toutes les réponses optimales, vous obtiendrez le score le plus élevé que n
vous publiez. Cependant, même si votre réponse n'est pas optimale, vous pouvez toujours obtenir le score si personne d'autre ne peut le battre.
Exemples de réponses et d'exemples fonctionnels
(Ces réponses ne sont pas encore vérifiées. Une vérification indépendante serait grandement appréciée.)
Merci à ETHproductions:
- n = 1 donne 2.
- n = 2 donne 5.
- n = 3 donne 21.
Regardons n = 2
plus en détail. Dans ce cas, la liste complète des séquences de distance de Hamming (représentées ici par des tuples) est:
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Nous pouvons voir que ce (0,0)
n'est pas proche de tout autre tuple. En fait , si nous prenons (0, 0)
, (0, 1)
, (1, 0)
, (2, 1)
, (1,2)
alors aucun de ces tuples sont proches de l' un des autres. Cela donne un score de 5
pour n = 2
.
Pour n = 3
la liste complète des séquences distinctes de distance de Hamming:
[(0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 2), (0, 2, 3), (0, 3, 0), (0, 3, 1), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 3, 0), (1, 3, 1), (1, 3, 2), (2, 0, 1), (2, 0, 2), (2, 0, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 3, 1), (2, 3, 2), (2, 3, 3), (3, 0, 2), (3, 0, 3), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 2), (3, 3, 3)]
De ces 48
séquences, nous pouvons choisir un ensemble de taille 21
afin qu'aucune paire de cet ensemble ne soit proche l'une de l'autre.
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 temporisations seront exécutées 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éponse principale
- Score de 4 pour 2, 5, 21, 83, 361 par Christian Sievers. C ++
- Score de 5 pour 2, 5, 21, 83, 372 par fəˈnɛtɪk. Javascript
Réponses:
C ++ utilisant la bibliothèque igraph
Merci pour cette belle opportunité d'apprendre une nouvelle bibliothèque!
Ce programme calcule désormais
2, 5, 21, 83, 361
rapidement. Vous pouvez contrôler l'impression des nœuds avec laPRINTNODES
constante.Le graphe utilisé a des arêtes supplémentaires entre les nœuds correspondant à des vecteurs de distance où l'un est proche (mais pas égal) de l'autre inversé. Cela accélère le calcul, et tout ensemble indépendant trouvé est bien sûr également l'un des graphiques d'origine. De plus, même s'il n'est pas complètement appliqué, l'ensemble indépendant calculé est fermé sous réversion. Je crois qu'il existe toujours un ensemble indépendant maximal avec cette propriété. Il y en a au moins un pour
n<=4
. (Je suis sûr que je peux montrer que 83 est optimal.)Pour compiler sur Debian, installez
libigraph0-dev
et faitesg++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o ig ig.cpp -ligraph
.Ancienne description:
La bibliothèque igraph a une fonction pour calculer la taille maximale d'un ensemble de sommets indépendant d'un graphe. Il peut gérer ce problème jusqu'à
n=3
en moins d'une seconde et ne se termine pas en quelques joursn=4
.Donc, ce que je fais, c'est décomposer le graphique en composants connectés et laisser la bibliothèque gérer les petits
MAXDIRECT
composants (moins que les nœuds). Pour les autres composants, je sélectionne un sommet et le supprime. Dans le meilleur des cas, cela divise le graphique en plusieurs composants, mais ce n'est généralement pas le cas. Quoi qu'il en soit, les composants (peut-être un seul) sont plus petits et nous pouvons utiliser la récursivité.Évidemment, la sélection du sommet est importante. Je prends juste un de degré maximal. J'ai trouvé que j'obtiens de meilleurs résultats (mais seulement pour
n=4
) lorsque j'utilise une liste de nœuds inversée. Cela explique la partie magique de laconstruct
fonction.Cela pourrait valoir la peine d'améliorer la sélection. Mais il semble plus important de reconsidérer les nœuds supprimés. En ce moment, je ne les regarde plus jamais. Certains d'entre eux peuvent être déconnectés de l'un des nœuds sélectionnés. Le problème est que je ne sais pas quels nœuds forment l'ensemble indépendant. D'une part, la suppression de nœuds renumérote les nœuds restants. Cela peut être géré en leur attachant des attributs. Mais pire, le calcul du nombre d'indépendance donne juste ce nombre. La meilleure alternative proposée par la bibliothèque est de calculer tous les plus grands ensembles indépendants, ce qui est plus lent (combien semble dépendre de la taille du graphique). Pourtant, cela semble la voie à suivre immédiate. Beaucoup plus vaguement, je pense également qu'il pourrait être utile de considérer si nous pouvons utiliser la façon particulière dont le graphique est défini.
Le cas
n=6
pourrait devenir accessible (du tout, pas nécessairement en 5 minutes) si je remplace la récursivité par une boucle utilisant une file d'attente pour les composants restants.J'ai trouvé intéressant de regarder les composants des graphiques. Car
n=4
, leurs tailles sont168, 2*29, 2*28, 3, 4*2, 4*1
. Seul le plus gros ne peut pas être traité directement.Pour
n=5
, les tailles sont1376, 2*128, 2*120, 119, several <=6
.Je m'attends à ce que ces tailles doubles correspondent à des graphiques isomorphes, mais cela ne semble pas valoir la peine car il y a toujours un seul composant dominant dominant:
Pour
n=6
, le plus grand composant contient des11941
nœuds (sur un total de15425
), les deux plus grands composants suivants ont une taille596
.Car
n=7
, ces chiffres le sont107593 (125232), 2647
.la source
g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o sievers sievers.cpp -ligraph
. Il importe où-ligraph
est.set
que j'utilise pour éviter les doublons, mais je n'ai même pas pensé à leur ordre quand j'ai écrit ce code. La boucle intérieure commençant ài+1
évite simplement de regarder une paire et aussi sa version permutée qui n'est pas nécessaire, et est le moyen le plus simple d'éviter les boucles (bords(a,a)
). Cela ne dépend pas de l'ordre dans lequel les nœuds viennent, je m'en fiche si j'obtiens(a,b)
ou(b,a)
.Javascript, Seq: 2,5,21,
8183,37267,349Géré pour augmenter la valeur de 4 en utilisant la suppression aléatoire des éléments au début de ma recherche. Curieusement, la suppression de 20 éléments avec plus de 6 connexions était plus rapide que la suppression de 5 éléments avec plus de 8 connexions ...
Cette séquence n'est probablement pas optimale pour 5 et pourrait ne pas être optimale pour 4. Cependant, aucun des nœuds n'est proche d'un autre dans l'ensemble.
Code:
Essayez-le en ligne!
Extrait qui peut être ajouté à la fin du programme pour montrer quelles séquences de distance de Hamming chaque séquence de distance de Hamming sélectionnée
Explication:
Tout d'abord, le code génère toutes les distances de hamming uniques à partir des sous-chaînes.
Ensuite, le code convertit cette liste en un graphique non orienté
Enfin, le code parcourt ce graphique, supprimant le sommet avec le plus de connexions à chaque cycle avant de restaurer les nœuds qui auraient désormais moins de connexions que le maximum actuel. Une fois ce cycle terminé, il affiche le nombre de nœuds restants
Ensembles:
1:
2:
3:
4:
5:
la source