Pour une image N par N , recherchez un ensemble de pixels tel qu'aucune distance de séparation ne soit présente plus d'une fois. Autrement dit, si deux pixels sont séparés par une distance d , alors ce sont les deux seuls pixels qui sont séparés par exactement d (en utilisant la distance euclidienne ). Notez que d n'a pas besoin d'être entier.
Le défi est de trouver un tel ensemble plus grand que quiconque.
spécification
Aucune contribution n'est requise - pour ce concours, N sera fixé à 619.
(Puisque les gens continuent de demander - le nombre 619 n'a rien de spécial. Il a été choisi pour être suffisamment grand pour rendre improbable une solution optimale, et assez petit pour permettre à une image N par N d'être affichée sans que Stack Exchange la rétrécisse automatiquement. Les images peuvent être affiché en taille réelle jusqu'à 630 par 630, et j'ai décidé d'aller avec le plus grand nombre premier qui ne dépasse pas cela.)
Le résultat est une liste d'entiers séparés par des espaces.
Chaque entier dans la sortie représente l'un des pixels, numéroté dans l'ordre de lecture anglais à partir de 0. Par exemple pour N = 3, les emplacements seraient numérotés dans cet ordre:
0 1 2
3 4 5
6 7 8
Vous pouvez générer des informations de progression pendant l'exécution si vous le souhaitez, tant que la sortie de notation finale est facilement disponible. Vous pouvez exporter vers STDOUT ou vers un fichier ou tout ce qui est plus facile à coller dans le juge d'extrait de pile ci-dessous.
Exemple
N = 3
Coordonnées choisies:
(0,0)
(1,0)
(2,1)
Sortie:
0 1 5
Gagnant
Le score est le nombre d'emplacements dans la sortie. Parmi les réponses valides qui ont le score le plus élevé, la première à publier la sortie avec ce score l'emporte.
Votre code n'a pas besoin d'être déterministe. Vous pouvez publier votre meilleure sortie.
Domaines de recherche connexes
(Merci à Abulafia pour les liens Golomb)
Bien qu'aucun de ces éléments ne soit identique à ce problème, ils sont tous deux de concept similaire et peuvent vous donner des idées sur la façon d'aborder ce problème:
- Règle de Golomb : le cas 1 dimension.
- Rectangle de Golomb : une extension bidimensionnelle de la règle de Golomb. Une variante du cas NxN (carré) connu sous le nom de tableau Costas est résolue pour tous les N.
Notez que les points requis pour cette question ne sont pas soumis aux mêmes exigences qu'un rectangle de Golomb. Un rectangle de Golomb s'étend du cas unidimensionnel en exigeant que le vecteur de chaque point à l'autre soit unique. Cela signifie qu'il peut y avoir deux points séparés par une distance de 2 horizontalement, et également deux points séparés par une distance de 2 verticalement.
Pour cette question, c'est la distance scalaire qui doit être unique, donc il ne peut pas y avoir une séparation horizontale et verticale de 2. Chaque solution à cette question sera un rectangle de Golomb, mais tous les rectangles de Golomb ne seront pas une solution valide pour cette question.
Limites supérieures
Dennis a utilement souligné dans le chat que 487 est une limite supérieure sur le score, et a donné une preuve:
Selon mon code CJam (
619,2m*{2f#:+}%_&,
), il y a 118800 nombres uniques qui peuvent être écrits comme la somme des carrés de deux entiers compris entre 0 et 618 (les deux inclus). n pixels nécessitent n (n-1) / 2 distances uniques entre eux. Pour n = 488, cela donne 118828.
Il y a donc 118 800 longueurs différentes possibles entre tous les pixels potentiels de l'image, et placer 488 pixels noirs entraînerait 118 828 longueurs, ce qui rend impossible leur caractère unique.
Je serais très intéressé d'entendre si quelqu'un a une preuve d'une limite supérieure inférieure à celle-ci.
Classement
(Meilleure réponse de chaque utilisateur)
Juge d'extrait de pile
la source
Réponses:
Python 3,
135136137Trouvé à l'aide d'un algorithme gourmand qui, à chaque étape, choisit le pixel valide dont l'ensemble des distances aux pixels choisis chevauche le moins celui des autres pixels.
Plus précisément, la notation est
et le pixel avec le score le plus bas est choisi.
La recherche est lancée avec le point
10
(ie(0, 10)
). Cette partie est réglable, donc commencer avec des pixels différents peut conduire à des résultats meilleurs ou pires.C'est un algorithme assez lent, donc j'essaie d'ajouter des optimisations / heuristiques, et peut-être un peu de retour en arrière. PyPy est recommandé pour la vitesse.
Quiconque essaie de trouver un algorithme devrait tester
N = 10
, pour lequel j'ai 9 (mais cela a pris beaucoup de réglages et d'essais différents points initiaux):Code
la source
N=10
et il existe de nombreuses dispositions distinctes avec 9 points, mais c'est le mieux que vous puissiez faire.SWI-Prolog, score de 131
À peine mieux que la réponse initiale, mais je suppose que cela fera démarrer les choses un peu plus. L'algorithme est le même que la réponse Python, à l'exception du fait qu'il essaie les pixels d'une manière alternative, en commençant par le pixel supérieur gauche (pixel 0), puis le pixel inférieur droit (pixel 383160), puis le pixel 1, puis le pixel 383159 , etc.
Contribution:
a(A).
Sortie:
Image de l'extrait de pile
la source
Haskell—
115130131135136Mon inspiration était le tamis d'Ératosthène et en particulier le tamis authentique d'Ératosthène , un article de Melissa E. O'Neill du Harvey Mudd College. Ma version originale (qui considérait les points dans l'ordre des index) a criblé les points extrêmement rapidement, pour une raison que je ne me souviens pas, j'ai décidé de mélanger les points avant de les "tamiser" dans cette version (je pense uniquement pour faciliter la génération de réponses différentes en utilisant une nouvelle graine dans le générateur aléatoire). Parce que les points ne sont plus dans aucun ordre, il n'y a plus vraiment de tamisage, et en conséquence, cela prend quelques minutes juste pour produire cette réponse unique de 115 points. Un KO
Vector
serait probablement un meilleur choix maintenant.Donc, avec cette version comme point de contrôle, je vois deux branches, revenir à l'algorithme «Genuine Sieve» et tirer parti de la monade List pour le choix, ou échanger les
Set
opérations contre des équivalentsVector
.Edit: Donc, pour la version de travail deux, je suis retourné vers l'algorithme de tamisage, amélioré la génération de «multiples» (assommant les indices en trouvant des points aux coordonnées entières sur des cercles de rayon égal à la distance entre deux points quelconques, semblable à la génération de multiples premiers ) et en apportant quelques améliorations de temps constant en évitant un recalcul inutile.
Pour une raison quelconque, je ne peux pas recompiler avec le profilage activé, mais je pense que le principal goulot d'étranglement est maintenant le retour en arrière. Je pense qu'explorer un peu de parallélisme et de simultanéité produira des accélérations linéaires, mais l'épuisement de la mémoire me limitera probablement à une amélioration de 2x.
Edit: la version 3 serpentait un peu, j'ai d'abord expérimenté une heuristique en prenant les index next suivants (après avoir tamisé à partir des choix précédents) et en choisissant celui qui a produit le prochain ensemble de knock-out minimum. Cela a fini par être beaucoup trop lent, alors je suis retourné à une méthode de force brute sur tout l'espace de recherche. Une idée de commander les points par distance à partir d'une certaine origine m'est venue et a conduit à une amélioration d'un seul point (dans le temps ma patience a duré). Cette version prend l'index 0 comme origine, cela peut valoir la peine d'essayer le point central de l'avion.
Edit: J'ai ramassé 4 points en réorganisant l'espace de recherche pour prioriser les points les plus éloignés du centre. Si vous testez mon code,
135136 est en fait ladeuxièmetroisième solution trouvée. Édition rapide: cette version semble la plus susceptible de rester productive si elle est exécutée. Je soupçonne que je peux égaliser à 137, puis manquer de patience en attendant 138.Une chose que je remarque (qui peut être utile à quelqu'un) est que si vous définissez la commande de point au centre du plan (c. -à- remove
(d*d -)
deoriginDistance
) l'image semble formé un peu comme une spirale premier clairsemée.Sortie
la source
d
minimise le nombre d'autres points exclus de la prise en compte en traçant des cercles de rayond
avec les centres des deux points choisis, où le périmètre ne touche que trois autres coordonnées entières (à 90, 180 et 270 degrés). le cercle), et la ligne bissectrice perpendiculaire ne croisant aucune coordonnée entière. Ainsi, chaque nouveau pointn+1
exclura d'6n
autres points de la considération (avec un choix optimal).Python 3, score 129
Ceci est un exemple de réponse pour commencer.
Juste une approche naïve en passant par les pixels dans l'ordre et en choisissant le premier pixel qui ne provoque pas de distance de séparation en double, jusqu'à ce que les pixels soient épuisés.
Code
Sortie
Image de l'extrait de pile
la source
Python 3, 130
À titre de comparaison, voici une implémentation de backtracker récursif:
Il trouve rapidement la solution de 130 pixels suivante avant de commencer à s'étouffer:
Plus important encore, je l'utilise pour vérifier les solutions pour les petits cas. Pour
N <= 8
, les optimales sont:Entre parenthèses figurent les premiers optimaux lexicographiques.
Non confirmé:
la source
Scala, 132
Numérise de gauche à droite et de haut en bas comme la solution naïve, mais essaie de commencer à différents emplacements de pixels.
Sortie
la source
Python, 134
132Voici un simple qui élimine au hasard une partie de l'espace de recherche pour couvrir une plus grande zone. Il itère les points à distance d'un ordre d'origine. Il saute les points qui sont à la même distance de l'origine et les départs anticipés s'il ne peut pas s'améliorer au mieux. Il fonctionne indéfiniment.
Il trouve rapidement des solutions avec 134 points:
3097 3098 2477 4333 3101 5576 1247 9 8666 8058 12381 1257 6209 15488 6837 21674 19212 26000 24783 1281 29728 33436 6863 37767 26665 14297 4402 43363 50144 52624 18651 9996 58840 42792 6295 69950 48985 347367477 7197 7197487 7197 7197 7197 7197 7997 9197 7997 7997 947 7607 247 7367477 247 7367 347 437 7367 7367 7367 7327 dans la vente de la vente des produits de la vente de la vente en France 113.313 88.637 122.569 11.956 36.098 79.401 61.471 135.610 31.796 4.570 150.418 57.797 4.581 125.201 151.128 115.936 165.898 127.697 162.290 33.091 20.098 189.414 187.620 186.440 91.290 206.766 35.619 69.033 351 186.511 129.058 228.458 69.065 226.046 210.035 235.925 164.324 18.967 254.416 130.970 17.753 248.978 57.376 276.798 456 283.541 293.423 257.747 204.626 298.427 249115 21544 95185 231226 54354 104483 280665 518 147181 318363 1793 248609 82260 52568 365227 361603 346849 331462 69310 90988 341446 229599 277828 382837 339014 323612 365040 269883 307597 374347 3162821 354698
Pour les curieux, voici quelques petits N brutaux:
la source
Fantom 96
J'ai utilisé un algorithme d'évolution, essentiellement ajouter k points aléatoires à la fois, faire cela pour j différents ensembles aléatoires, puis choisir le meilleur et répéter. Réponse assez terrible en ce moment, mais c'est la faire fonctionner avec seulement 2 enfants par génération pour des raisons de vitesse, ce qui est presque juste aléatoire. Je vais jouer un peu avec les paramètres pour voir comment ça se passe, et j'ai probablement besoin d'une meilleure fonction de notation que le nombre de places libres restantes.
Sortie
la source
Python 3, 119
Je ne me souviens plus pourquoi j'ai nommé cette fonction
mc_usp
, même si je soupçonne qu'elle a quelque chose à voir avec les chaînes de Markov. Ici, je publie mon code que j'ai exécuté avec PyPy pendant environ 7 heures. Le programme essaie de créer 100 ensembles de pixels différents en choisissant aléatoirement des pixels jusqu'à ce qu'il ait vérifié chaque pixel de l'image et en renvoyant l'un des meilleurs ensembles.Sur une autre note, à un moment donné, nous devrions vraiment essayer de trouver une limite supérieure pour
N=619
mieux que 488, car à en juger par les réponses ici, ce nombre est beaucoup trop élevé. Le commentaire de Rowan Blush sur la façon dont chaque nouveau pointn+1
peut potentiellement supprimer des6*n
points avec un choix optimal semblait être une bonne idée. Malheureusement, lors de l'inspection de la formulea(1) = 1; a(n+1) = a(n) + 6*n + 1
, où sea(n)
trouve le nombre de points supprimés après avoir ajouté desn
points à notre ensemble, cette idée peut ne pas être la meilleure. Vérifier quanda(n)
est supérieur àN**2
,a(200)
étant plus grand que ce qui619**2
semble prometteur, maisa(n)
plus grand que cela10**2
esta(7)
et nous avons prouvé que 9 est la limite supérieure réelle deN=10
. Je vous tiendrai au courant pendant que j'essaierai de chercher une meilleure limite supérieure, mais toutes les suggestions sont les bienvenues.Sur ma réponse. Tout d'abord, mon ensemble de 119 pixels.
Deuxièmement, mon code, qui choisit au hasard un point de départ à partir d'un octant du carré 619x619 (puisque le point de départ est par ailleurs égal en rotation et en réflexion), puis tous les autres points du reste du carré.
la source