Implementiere das Spiel des Lebens in 3D


17

Die Herausforderung besteht darin, die kürzeste Implementierung des Spiels des Lebens in 3D zu finden ( Beispiel ). Das sind die Regeln:

Zellen (in diesem Fall Würfel) mit nur 1 oder weniger Nachbarn sterben wie durch Einsamkeit.
Wenn genau 5 Zellen eine leere Zelle umgeben, züchten sie und füllen sie.
Wenn eine Zelle 8 oder mehr Nachbarn hat, stirbt sie an Überfüllung.

Stellen Sie mindestens 10x10x10 ein, wobei die Ebenen einzeln wie folgt ausgegeben werden:

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 X 0 0 X 0 0 0 0 0
0 0 X X X 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

Natürlich wird auch eine grafische 3D-Simulation akzeptiert.
Die Startposition kann fest codiert sein, muss jedoch funktionieren, wenn sie in eine Startposition geändert wird. Es muss in der Lage sein, eine beliebige Anzahl von Generationen zu berechnen, und der Benutzer muss manuell nach der nächsten Generation fragen können.

Kürzester Code in Zeichen gewinnt!

Ich habe dies für jede (Cube-) Größe selbst implementiert: http://jensrenders.site88.net/life3D.htm Sie können dies zum Testen verwenden und Ihren Code auf meinen Code stützen, obwohl ich ihn nicht kommentiert habe .


1
Impliziert der Code-Golf-Tag aus Ihrer Aussage die kürzeste Implementierung . Bitte überprüfen Sie, ob es das ist, was Sie wollen. Sie sollten auch einige Details über die Eingabe, die Anzahl der Zyklen und die Anzahl der animierten Ja- / Nein-Zyklen angeben, da Code-Golf eine zuverlässige Spezifikation benötigt.
Howard

@Howard Ich habe ein paar weitere Spezifikationen hinzugefügt und ja, ich habe den Code-Golf-Tag vergessen;) Danke dafür.
Jens Renders

@ PeterTaylor Ja genau 5, ich werde es bearbeiten.
Jens Renders

Ich würde Einzelheiten zum Ausgabeformat hinzufügen (z. B. muss jede Zelle durch ein Leerzeichen getrennt sein, wie in Ihrem Beispiel, eine neue Zeile zwischen jeder Rasterebene der Ausgabe, lebende und tote Zellen müssen durch verschiedene Zeichen dargestellt werden, und diese müssen sichtbare Zeichen sein .) Bedenken Sie auch, dass es unwahrscheinlich ist, dass Sie grafische Simulationen erhalten, wenn Sie als Code-Golf gerahmt sind.
Jonathan Van Matre

Wollten Sie wirklich alle in diesem Meta-Thread besprochenen Lücken verbieten oder nur diejenigen, die die (Nicht-) Genehmigungskriterien erfüllen (+5 Punkte, mindestens doppelt so viele positive wie negative Stimmen)? Weil ich bin sicher , ich könnte völlig denke an ein paar ziemlich interessante „Lücken“ zu diskutieren ... ;-)
Ilmari Karonen

Antworten:


14

Mathematica - 120 Bytes

g=CellularAutomaton[{(l=Flatten@#;c=l[[14]];n=Total@Drop[l,{14}];Which[n<2||n>7,0,n==5||c==1,1,0<1,0])&,{},{1,1,1}},##]&

Sicher kein Anwärter auf den Sieg, aber das war nicht meine Absicht. Dies könnte wahrscheinlich auch erheblich gesenkt werden, indem man nur die Regelnummer herausfindet. Ich wollte eigentlich nur eine Visualisierung schreiben (obwohl ich mir eigentlich sicher bin, dass es bereits Unmengen davon gibt). Auf geht's):

animateGol3d[size_, i_, n_] := 
  ListAnimate[
    Graphics3D[
      Cuboid /@ Position[#, 1], 
      PlotRange -> {{0, size}, {0, size}, {0, size}} + 1
    ] & /@ g[i, n]
  ];

Und nachdem ich mit ein paar Anfangsbedingungen experimentiert hatte, bekam ich Dinge wie die folgenden:

Bildbeschreibung hier eingeben

Und hier ist einer mit einer Rastergröße von 20x20x20. Das Simulieren und Rendern dauerte einige Sekunden:

Bildbeschreibung hier eingeben

Dies setzt übrigens periodische Randbedingungen voraus.


Treten diese wirklich in einen Gleichgewichtszustand ein oder ist es nur das Anhalten der Animation? Wenn erstere, hast du mir ein paar nette Ideen gegeben ...
Kroltan

1
@Kroltan Es ist schon eine Weile her, aber ich bin mir ziemlich sicher, dass sie das Gleichgewicht erreicht haben.
Martin Ender

1
Nett, danke. Einzelne Scheiben des Gleichgewichts wirken sehr raumgreifend, zum Beispiel als rougelartiges Spiel.
Kroltan

12

APL, 46

Es hat einige Zeit gedauert, aber ich habe es auf 46 Zeichen reduziert:

{(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵}

Dies ist eine Funktion, die eine boolesche 3D-Matrix beliebiger Größe verwendet und die nächste Generation gemäß den angegebenen Regeln berechnet. Da keine Randbedingungen festgelegt wurden, habe ich mich dafür entschieden, mich wie im torusförmigen Raum um die andere Seite zu wickeln.

Erläuterung

{                           ⊂⍵}   Take the argument matrix and enclose it in a scalar
               (i←2-⍳3)           Prepare an array with values -1 0 1 and call it i
                       ⌽[2]¨      Shift the matrix along the 2nd dim. by each of -1 0 1
           i∘.⊖                   Then for each result do the same along the 1st dimension
       i∘.⌽                       And for each result again along the 3rd dimension
 m←⊃+/,                           Sum element-wise all 27 shifted matrices and call it m

Das Zwischenergebnis mist eine Matrix mit der gleichen Form wie die ursprüngliche Matrix, die für jedes Element zählt, wie viele Zellen in seiner 3 × 3 × 3-Nachbarschaft einschließlich sich selbst leben. Dann:

           |5.5-m   For each element (x) in m, take its distance from 5.5
       ⍵∧3>         If that distance is <3 (which means 3≤x≤8) and the original cell was 1,
 (5=m)∨             or if the element of m is 5, then the next generation cell will be 1.

Beispiel

Definieren Sie eine zufällige 4 × 4 × 4-Matrix mit ungefähr 1/3 Zellen = 1 und berechnen Sie die 1. und 2. Generation. Die ⊂[2 3]Vorderseite ist nur ein Trick, um die Ebenen horizontal statt vertikal zu drucken:

      ⊂[2 3] m←1=?4 4 4⍴3
 1 0 0 0  1 0 1 0  1 0 1 0  0 0 0 1 
 1 1 0 0  0 0 0 0  0 0 0 1  1 0 1 0 
 0 0 0 0  0 1 0 0  0 0 0 0  0 0 1 0 
 1 1 0 0  0 0 0 1  1 0 0 1  0 0 1 0 
      ⊂[2 3] {(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵} m
 0 0 0 0  0 0 1 0  1 0 1 0  0 0 0 0 
 1 0 0 0  0 0 1 0  0 0 0 0  1 0 1 0 
 0 0 0 0  0 1 0 0  0 0 0 0  0 0 1 0 
 1 1 0 0  0 0 0 0  1 0 0 0  0 0 1 0 
      ⊂[2 3] {(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵}⍣2⊢ m
 0 0 1 0  1 0 1 0  1 0 1 0  0 0 0 0 
 1 0 1 0  0 0 1 1  0 0 0 0  1 0 1 0 
 1 0 0 0  1 1 0 0  0 0 1 0  1 0 1 0 
 1 1 1 0  1 0 0 1  1 0 1 0  0 0 1 0 

+1 Sehr schöne Antwort! In der Tat wurden keine Grenzen festgelegt, so dass ein Umlauf zulässig ist.
Jens Renders

9

J - 42 Zeichen

Wir gehen von einer ringförmigen Platte (umlaufend) in allen drei Dimensionen aus. Die automatische Anzeige der Ergebnisse von J scheint der Ausgabespezifikation zu folgen, wobei 1für lebende Zellen und 0für tote Zellen verwendet wird . Dieser Code funktioniert auf Brettern mit einer beliebigen Breite, Länge und Höhe (10 x 10 x 10, 4 x 5 x 6 usw.).

(((1&<*<&8)@-*]+.5=-)~[:+/(,{3#<i:1)|.&><)

Eine Erklärung folgt:

  • ,{3#<i:1 - Unterausdruck der Liste der Offsets für die Zelle und alle ihre Nachbarn.
    • <i:1 - Die Liste der Ganzzahlen zwischen 1 und einschließlich -1.
    • ,{3#- Machen Sie drei Kopien der Liste ( 3#) und nehmen Sie das kartesische Produkt ( ,{).
  • (,{3#<i:1)|.&><- Verschieben Sie für jeden Satz von 3D-Offsets das Array. Bei einem Wert von 3 Zeichen können Sie ändern |.&>, |.!.0&>um kein Wraparound zu erhalten.
  • [:+/ - Summiere alle verschobenen Bretter.
  • ((1&<*<&8)@-*]+.5=-)~- Das lange äußere Verb war ein Haken, so dass es das Brett links und rechts und die Seite rechts, die wir verschoben und summiert haben, aufnimmt. Die ~tauschen dies gegen dieses innere Verb aus.
    • 5=- - 1 in jeder Zelle, bei der die Summe der verschobenen Karten abzüglich der ursprünglichen Karte (dh der Anzahl der Nachbarn) gleich 5 ist, und 0 in allen anderen.
    • ]+. - Logisch ODER oben mit der Originalplatine.
    • (1&<*<&8) - 1, wenn die Zahl ausschließlich zwischen 1 und 8 verglichen wird, sonst 0.
    • (1&<*<&8)@-* - Vergleichen Sie (wie oben) die Anzahl der Nachbarn und multiplizieren Sie (dh logisches UND, wenn die Domäne nur 1 oder 0 ist) das logische ODER-Ergebnis damit.

Die Verwendung erfolgt wie bei der APL. Wenden Sie die Funktion für jeden Schritt nur auf die Anfangskarte an. J hat einen funktionalen Netzbetreiber ^:, um dies zu vereinfachen.

   life =: (((1&<*<&8)@-*]+.5=-)~[:+/(,{3#<i:1)|.&><)  NB. for convenience
   board =: 1 = ?. 4 4 4 $ 4  NB. "random" 4x4x4 board with approx 1/4 ones
   <"2 board  NB. we box each 2D plane for easier viewing
+-------+-------+-------+-------+
|0 0 0 0|1 1 0 0|0 1 0 0|0 0 1 0|
|0 1 0 0|0 0 0 0|0 0 0 1|1 0 0 0|
|0 0 0 0|0 0 1 0|0 1 0 0|0 0 0 1|
|1 1 0 0|1 0 0 0|0 0 0 1|0 1 1 0|
+-------+-------+-------+-------+
   <"2 life board
+-------+-------+-------+-------+
|0 0 0 0|0 1 0 1|0 1 0 0|0 0 1 0|
|1 1 1 1|0 0 0 0|0 0 0 1|1 1 0 0|
|0 0 0 0|0 0 1 1|0 1 0 0|0 0 0 1|
|1 0 0 0|1 0 0 1|0 0 0 1|0 1 1 1|
+-------+-------+-------+-------+
   <"2 life^:2 board  NB. two steps
+-------+-------+-------+-------+
|0 0 0 0|0 1 0 0|0 1 0 0|0 0 0 0|
|0 1 0 0|0 0 0 0|0 0 0 1|0 1 0 0|
|0 0 0 0|0 0 0 0|0 1 0 0|0 0 0 0|
|0 0 0 0|0 0 0 1|0 0 0 0|0 1 1 1|
+-------+-------+-------+-------+
   <"2 life^:3 board  NB. etc
+-------+-------+-------+-------+
|0 1 0 0|1 1 1 0|0 1 0 0|0 1 0 0|
|0 1 0 0|1 0 1 0|1 0 1 0|1 1 1 0|
|1 0 0 0|0 0 0 0|0 1 0 0|0 1 0 0|
|0 0 1 0|0 0 0 0|0 1 0 0|0 1 1 0|
+-------+-------+-------+-------+

Ich sage "zufällig", weil das ?.Grundelement jedes Mal reproduzierbare zufällige Ergebnisse liefert, indem ein fester Startwert verwendet wird. ?ist der wahre RNG.


Fluch J und sein übles |.Verb !! Gut gemacht.
Tobia
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.