Ce défi est en partie un défi d'algorithmes, en partie un défi d'optimisation et en partie simplement un défi de code le plus rapide.
Une matrice cyclique est entièrement spécifiée par sa première ligne r
. Les lignes restantes sont chacune des permutations cycliques de la ligne r
avec un décalage égal à l'index de la ligne. Nous autoriserons les matrices cycliques qui ne sont pas carrées de sorte qu'il leur manque simplement certaines de leurs dernières lignes. Nous supposons cependant toujours que le nombre de lignes n'est pas supérieur au nombre de colonnes. Par exemple, considérons la matrice cyclique 3 x 5 suivante.
10111
11011
11101
Nous disons qu'une matrice a la propriété X si elle contient deux ensembles de colonnes non vides avec des indices non identiques qui ont la même somme (vectorielle). La somme vectorielle de deux colonnes est simplement une somme par élément des deux colonnes. C'est la somme de deux colonnes contenant des x
éléments chacune est une autre colonne contenant des x
éléments.
La matrice ci-dessus a trivialement la propriété X car les première et dernière colonnes sont les mêmes. La matrice d'identité n'a jamais la propriété X.
Si nous supprimons simplement la dernière colonne de la matrice ci-dessus, nous obtenons un exemple qui n'a pas la propriété X et donnerait un score de 4/3.
1011
1101
1110
La tâche
La tâche consiste à écrire du code pour trouver la matrice cyclique au score le plus élevé dont les entrées sont toutes 0 ou 1 et qui n'a pas la propriété X.
But
Votre score sera le nombre de colonnes divisé par le nombre de lignes de votre matrice de meilleur score.
Tie break
Si deux réponses ont le même score, celle soumise en premier l'emporte.
Dans le cas (très) peu probable où quelqu'un trouverait une méthode pour obtenir des scores illimités, la première preuve valable d'une telle solution sera acceptée. Dans le cas encore plus improbable où vous pouvez trouver une preuve d'optimalité d'une matrice finie, j'attribuerai bien sûr également la victoire.
Allusion
Obtenir un score de 12/8 n'est pas trop difficile.
Langues et bibliothèques
Vous pouvez utiliser n'importe quelle langue disposant d'un compilateur / interprète / etc disponible gratuitement. pour Linux et toutes les bibliothèques qui sont également disponibles gratuitement pour Linux.
Entrées principales
- 36/19 de Peter Taylor (Java)
- 32/17 par Suboptimus Prime (C #)
- 21/12 par moitié (Python 2)
la source
01
a la propriété X parce que l'ensemble de la première colonne a la même somme vectorielle que l'ensemble vide. Peut-être vouliez-vous dire des ensembles de colonnes non vides? Je pense que c'est plus propre de ne pas le changer.01
possède une propriété X:(1) = (0) + (1)
. Si vous souhaitez exclure cela, vous devez dire que les deux ensembles de colonnes doivent être disjoints.2^m
combinaisons de colonnes à vérifier la propriété X. Si nous pouvions en quelque sorte concevoir un schéma de "rencontre au milieu" (voir le problème de la "somme des sous-ensembles"), cela pourrait probablement le réduire àm * 2^(m/2)
...Réponses:
16/9 20/11 22/12 28/15 30/16 32/1734/18 36/19 (Java)Cela utilise un certain nombre d'idées pour réduire l'espace de recherche et les coûts. Consultez l'historique des révisions pour plus de détails sur les versions antérieures du code.
0
et1
) et en travaillant; J'utilise l'algorithme décrit dans Un code gris pour les colliers à densité fixe et les mots Lyndon à temps amorti constant , Sawada et Williams, Theoretical Computer Science 502 (2013): 46-54.BigInteger
pour donner un test exact. J'obtiens une amélioration significative de la vitesse, au risque de faux négatifs, en faisant fonctionner modulo un grand prime et en gardant le tout dans les primitives. Le nombre premier que j'ai choisi est le plus grand, inférieur à 2 57 , car cela permet de multiplier par la base de ma représentation vectorielle théorique sans déborder.{-1,0,1}^m
a également sa négation,{-1,0,1}^m
il est seulement nécessaire de stocker l'un des deux.2n/(n+1)
, j'accélère les choses en testant simplement cela.Le premier trouvé est
et c'est le seul succès en 15 heures.
Petits gagnants:
la source
n
plutôt querows
, bien qu'il soit à sécurité intégrée dans le sens où il rejetterait les solutions valides plutôt que d'accepter les solutions invalides. Cela n'affecte pas non plus les résultats.Python 2 - 21/12
En train de prouver qu’il
2-(3/n)
existe toujours unn
Inspiré par cette question , j'ai utilisé la séquence De Bruijn pour forcer brutalement les matrices possibles. Et après le bruteforcing pour
n=6,7,8,9,10
, j'ai trouvé un modèle dont la solution la plus élevée est toujours sous la forme(n, 2n-3)
.J'ai donc créé une autre méthode pour renforcer brutalement cette forme de matrice et utiliser le multitraitement pour accélérer les choses, car cette tâche est hautement distribuable. Dans Ubuntu 16 cœurs, il peut trouver une solution
n=12
en environ 4 minutes:La majeure partie du calcul va à la vérification de la propriété X, qui nécessite de vérifier tous les sous-ensembles (il existe des
2^(2n-3)
sous - ensembles)Notez que je tourne la première ligne vers la gauche, pas vers la droite comme dans la question. Mais ceux-ci sont équivalents car vous pouvez simplement inverser la matrice entière. =)
Le code:
Ancienne réponse, pour référence
Jusqu'à présent, la solution optimale (
n=10
):Pour
n=7
:Une solution avec la forme décrite par OP (
n=8
):Mais un meilleur (
n=8
):Il a également trouvé une autre solution optimale à
n=9
:Le code est comme suit. C'est juste de la force brute, mais au moins, il peut trouver quelque chose de mieux que la revendication d'OP =)
la source
n >= 31
, ce qui implique que je devrais vérifier les2^(2n-3) = 2^59
combinaisons de vecteurs 31 dimensions. Ne se terminera pas de notre vivant = Dn*(2n-3)
24/13 26/14 28/15 30/1632/17 (C #)Edit: Supprimé les informations obsolètes de ma réponse. J'utilise principalement le même algorithme que Peter Taylor ( Edit: il semble qu'il utilise un meilleur algorithme maintenant), bien que j'aie ajouté certaines de mes propres optimisations:
HasPropertyXFast
fonction, qui vérifie rapidement s'il y a de petits ensembles avec des sommes égales avant d'utiliser l'approche "rencontrer au milieu".HasPropertyXFast
fonction, je commence par vérifier les jeux de colonnes avec 1 colonne, puis avec 2, 3 et ainsi de suite. La fonction revient dès que la première collision de sommes de colonne est trouvée. En pratique, cela signifie que je dois généralement vérifier quelques centaines ou milliers de jeux de colonnes plutôt que des millions.long
variables pour stocker et comparer des colonnes entières et leurs sommes vectorielles. Cette approche est au moins un ordre de grandeur plus rapide que la comparaison de colonnes en tant que tableaux.long
le type de données et pour mes modèles d'utilisation.Sortie du programme:
Code:
Fichier de configuration:
la source
ulong
et de laisser le changement de cap au lieu d'utiliserBigInteger
.GetSumOfColumns
ajoute une boucle supplémentaire dont je m'attendrais à coûter plus que ce facteur de 2. Le tri du masque semble intéressant: peut-être pourriez-vous modifier la réponse pour en parler un peu? (Et à un moment donné, j'expérimenterai une autre façon de faire l'abandon précoce: la raison pour laquelle je ne peux pas le faire est que HashSet ne prend pas en charge l'itération et la modification simultanées, mais j'ai des idées pour éviter le besoin d'un itérateur) .