Optimiser le jeu de la vie
-
28-10-2019 - |
Question
J'écris un programme de jeu de la vie en mathématique, mais il y a une mise en garde en ce sens que je dois pouvoir appliquer les règles de reproduction à un certain pourcentage des cellules, je veux essayer une nouvelle méthode utilisant MapAt mais liveNeighbors ne le fait pasne fonctionne pas par élément, et je ne peux pas penser à un moyen de le réparer sans faire exactement ce que j'ai fait avant (beaucoup d'indexation désordonnée), est-ce que quelqu'un a des suggestions?(Je suppose que ce sera plus efficace que l'ancienne méthode, qui est répertoriée ci-dessous, sinon faites-le moi savoir, je ne suis qu'un débutant!).
Ce que j'essaie de faire:
Map[ArrayPlot,FixedPointList[MapAt[update[#,liveNeighbors[#]]&,#,coords]&,Board, 1]]
Ce que j'ai déjà fait:
LifeGame[ n_Integer?Positive, steps_] := Module [{Board, liveNeighbors, update},
Board = Table [Random [Integer], {n}, {n}];
liveNeighbors[ mat_] :=
Apply[Plus,Map[RotateRight[mat,#]&,{{-1,-1},{-1, 0},{-1,1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}]];
update[1, 2] := 1;
update[_, 3] := 1;
update[ _, _] := 0;
SetAttributes[update, Listable];
Seed = RandomVariate[ProbabilityDistribution[0.7 UnitStep[x] + 0.3 UnitStep[x - 1], {x, 0, 1, 1}], {n, n}];
FixedPointList[Table[If[Seed[[i, j]] == 1,update[#[[i, j]], liveNeighbors[#][[i, j]]],#[[i, j]]], {i, n}, {j, n}]&, Board, steps]]]
Merci!
La solution
In[156]:=
LifeGame2[n_Integer?Positive, steps_] :=
Module[{Board, liveNeighbors, update},
Board = RandomInteger[1, {n, n}];
liveNeighbors[mat_] :=
ListConvolve[{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}},
ArrayPad[mat, 1, "Periodic"]];
SetAttributes[update, Listable];
Seed = RandomVariate[BernoulliDistribution[0.3], {n, n}];
update[0, el_, nei_] := el;
update[1, 1, 2] := 1;
update[1, _, 3] := 1;
update[1, _, _] := 0;
FixedPointList[MapThread[update, {Seed, #, liveNeighbors[#]}, 2] &,
Board, steps]
]
Cette implémentation fait la même chose que la vôtre, sauf qu'elle est beaucoup plus rapide:
In[162]:= AbsoluteTiming[
res1 = BlockRandom[SeedRandom[11]; LifeGame[20, 100]];]
Out[162]= {6.3476347, Null}
In[163]:= Timing[BlockRandom[Seed[11]; LifeGame2[20, 100]] == res1]
Out[163]= {0.047, True}
Autres conseils
En supposant que vous n'ayez pas à rouler votre propre code pour un problème de devoirs, avez-vous envisagé d'utiliser simplement le CellularAutomaton
?
Directement de la documentation, la règle 2D CA:
GameOfLife = {224, {2, {{2, 2, 2}, {2, 1, 2}, {2, 2, 2}}}, {1, 1}};
Et parcourez une grille de 100 x 100 pendant 100 étapes:
ArrayPlot[CellularAutomaton[GameOfLife, RandomInteger[1, {100, 100}], {{{100}}}]]
Cela vous donnerait au moins une base de référence pour une comparaison de vitesse.
Au lieu de MapAt
, vous pouvez utiliser Part
avec la syntaxe Span
pour remplacer un sous-tableau entier à la fois:
a = ConstantArray[0, {5, 5}];
a[[2 ;; 4, 2 ;; 4]] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
HTH!