Étant donné un entier N positif, déterminez le motif de départ sur une grille N x N qui donne la séquence non répétitive la plus longue selon les règles du jeu de la vie, et se termine par un motif fixe (cycle de longueur 1), joué sur un tore.
L'objectif n'est pas le programme le plus court, mais le plus rapide.
Puisque le monde est fini, vous finirez par finir dans une boucle, répétant ainsi un état déjà visité. Si cette boucle a la période 1, alors le modèle de départ est un candidat valide.
Sortie: modèle de départ et nombre total d'états uniques dans la séquence (y compris le modèle de départ).
Maintenant, le tore 1x1 est spécial, car une cellule peut être considérée comme voisine d'elle-même ou non, mais en pratique, il n'y a pas de problème, une seule cellule vivante mourra dans les deux cas (de surpopulation ou de solitude). Ainsi, l'entrée 1 donne une séquence de longueur 2, la séquence étant une cellule vivante, puis morte à jamais.
La motivation de cette question est qu'il s'agit d'un analogue de la fonction de castor occupé, mais certainement moins complexe, car nous avons une limite sur la mémoire. Ce sera une belle séquence à inclure également sur OEIS.
Pour N = 3, la longueur de la séquence est de 3, tout motif sur le côté gauche atteint un carré 3x3 complètement noir, puis meurt. (Tous les motifs faisant partie d'un cycle ont été supprimés).
la source
Réponses:
C ++ jusqu'à N = 6
Cette technique est centrée sur une fonction d'état suivant rapide. Chaque carte est représentée sous la forme d'un masque de bits de N ^ 2 bits, et des astuces bit-twiddly sont utilisées pour calculer l'état suivant pour toutes les cellules à la fois.
next
compile jusqu'à environ200100 instructions d'assemblage pour N <= 8. Ensuite, nous faisons simplement l'essai standard tous les états jusqu'à ce qu'ils se répètent et choisissons le plus long.Prend quelques secondes jusqu'à 5x5, quelques heures pour 6x6.
la source
next
en comptant plutôt qu'en triant.#define H(x,y){x^=y;y&=(x^y);}
puis quelque chose commeH(n1,n2);H(n3,n4);H(n5,n6);H(n7,n8);H(n1,n3);H(n5,n7);H(n2,n4);H(n6,n8);H(n1,n5);H(n3,n7);H(n2,n6);H(n2,n3);H(n2,n5); return n2 & (b | n1) & ~(n3|n4|n5|n6|n7|n8) & ALL;
Je vois les approches de solution possibles suivantes:
Next(board)
fonction, nous constatons qu'elle présente certains avantages, bien que pas autant que je l'espérais à l'origine.Prev2
.Je ne pense pas que la micro-optimisation me permettra de rattraper le code de Keith, mais pour l'intérêt, je posterai ce que j'ai. Cela résout N = 5 en environ une minute sur une machine à 2 GHz en utilisant Mono 2.4 ou .Net (sans PLINQ) et en environ 20 secondes en utilisant PLINQ; N = 6 s'exécute pendant plusieurs heures.
la source
Facteur
Quelques statistiques de temps:
Et le test 5 a fait planter le REPL. Hmph. La partie la plus inefficace du programme est probablement la fonction jeu-séquence. Je pourrais peut-être l'améliorer plus tard.
la source