Le plus court jeu de la vie


59

Le jeu de la vie de Conway est l'exemple classique de l'automatisation cellulaire. Les cellules forment une grille carrée et chacune a deux états: vivant ou mort. A chaque tour, chaque cellule se met à jour simultanément en fonction de son état et de celui de ses huit voisins:

  • Une cellule vivante reste en vie si elle a exactement deux ou trois voisins vivants
  • Une cellule morte devient vivante si elle a exactement trois voisins vivants

Votre mission, si vous acceptez de l'accepter, consiste à coder la mise en œuvre la plus courte de Game of Life dans votre langue préférée.

Les règles:

  • La grille doit être au moins 20x20
  • La grille doit envelopper (donc la grille est comme la surface d'un tore)
  • Votre implémentation doit permettre à l'utilisateur de saisir ses propres modèles de départ.
  • GoL est un peu inutile si vous ne pouvez pas voir ce qui se passe, il doit donc y avoir une sortie visuelle de l'automate en marche, le résultat de chaque tour étant affiché suffisamment longtemps pour être vu!

8
Précédemment sur Stack Overflow: Code Golf: Le jeu de la vie de Conway , et veillez à consulter le lien relatif à la mise en œuvre de l'APL dans les commentaires.
dmckee

1
Ah, je n'ai pas vu ça. Mais ceci est légèrement différent non (sauf moi en supprimant le travail qui rassemble le défi?)
Griffin

6
Ce n'est pas un problème. De nombreux casse-tête déjà exécutés sur Stack Overflow ont également été réalisés ici, mais les gens vous diront que je suis obsédé par l'idée de faire le lien avec des défis similaires.
dmckee

@Griffin: Vous pouvez supprimer tous ceux qui ;précèdent }. Aussi, vars peut être éliminé à certains moments (si cela ne casse pas votre code). Et pour une ligne fors, ifvous pouvez éliminer s etc, le { }tout à : for(...) for(...) dosomething().
pimvdb

@pimvdb, bravo, je n'ai pas encore tout joué au golf, je n'ai pas eu le temps. je voulais juste montrer que je pouvais aussi essayer, plutôt que de poser des défis sans rien faire. Le golf sera-t-il au maximum bientôt.
Griffin

Réponses:


27

Toile HTML5 avec JavaScript, 940 639 586 519 caractères

<html><body onload="k=40;g=10;b=[];setInterval(function(){c=[];for(y=k*k;y--;){n=0;for(f=9;f--;)n+=b[(~~(y/k)+k+f%3-1)%k*k+(y+k+~~(f/3)-1)%k];c[y]=n==3||n-b[y]==3;r.fillStyle=b[y]?'red':'tan';r.fillRect(y%k*g,~~(y/k)*g,g-1,g-1)}if(v.nextSibling.checked)b=c},1);v=document.body.firstChild;v.width=v.height=g*k;v.addEventListener('click',function(e){b[~~((e.pageY-v.offsetTop)/g)*k+~~((e.pageX-v.offsetLeft)/g)]^=1},0);r=v.getContext('2d');for(y=k*k;y--;)b[y]=0"><canvas></canvas><input type="checkbox"/>Run</body></html>

J'ai toujours voulu faire quelque chose avec canvas, donc voici ma tentative (version originale en ligne ). Vous pouvez changer de cellule en cliquant sur (également possible en mode de fonctionnement).

Vous pouvez maintenant aussi essayer la nouvelle version ici .

Malheureusement, il y a un problème que je ne pouvais pas encore résoudre. La version en ligne comporte 11 caractères de plus, car jsFiddle place un nœud de texte juste avant le canevas (pourquoi?) Et le canevas n’est donc plus le premier enfant.

Edit 1: Beaucoup d’optimisations et de restructurations.

Edit 2: Plusieurs modifications mineures.

Edit 3: En ligne le bloc de script complet plus les modifications mineures.


Sympa, mais change le délai d’intervalle pour le 1rendre aussi rapide que le mien plutôt que de marcher lentement. De plus, si vous souhaitez implémenter le dessin (plutôt que de cliquer sur chaque carré), vous pouvez arrondir la position de la souris à la taille de bloc la plus proche et remplir le rectangle à cet endroit. Plus de personnages mais plus de points.
Griffin

Vous pouvez remplacer new Array('#FFF','#800')par ['#FFF','#800'].
Lowjacker

Bien que disant cela à propos de dessiner, mon super-golfeur ne permet pas de dessiner et est laid comme un péché. Haha. Vous pouvez définir vos deux couleurs dans le stableau sur tanet redpuisque ce sont les deux couleurs avec les représentations les plus courtes - vous enregistre deux caractères. Aussi, si possible, mettez la version littérale de jdans l'intervalle. Je suis sûr qu'il y a encore beaucoup à faire.
Griffin

@Griffin et Lowjacker: merci beaucoup. Je suis également convaincu que vous pourrez jouer au golf beaucoup plus (et que vous avez déjà quelques idées). Malheureusement, je n'ai pas trouvé le temps de le faire. Une meilleure version golfée suivra demain - j'espère ...
Howard,

2
Vous pouvez supprimer les balises html et body. Il fonctionnera de la même manière
arodebaugh

32

Python, 219 caractères

Je suis allé pour golfage maximum, avec juste assez d’interface pour répondre à la question.

import time
P=input()
N=range(20)
while 1:
 for i in N:print''.join(' *'[i*20+j in P]for j in N)
 time.sleep(.1);Q=[(p+d)%400 for d in(-21,-20,-19,-1,1,19,20,21)for p in P];P=set(p for p in Q if 2-(p in P)<Q.count(p)<4)

Vous l'exécutez comme ceci:

echo "[8,29,47,48,49]" | ./life.py

Les nombres dans la liste représentent les coordonnées des cellules de départ. La première ligne est 0-19, la deuxième ligne est 20-39, etc.

Exécutez-le dans un terminal avec 21 lignes et il a l'air plutôt élégant.


1
Cela aurait totalement dû gagner. Je suppose que la "facilité de saisie" était pondérée assez haut.
primo

@primo, j'irais même jusqu'à suggérer que mma devrait avoir un concours distinct.
luser droog

2
Alors, cette vie de Py est-elle alors?
Christopher Wirt

Vous pouvez toujours enregistrer un autre caractère ... 2-(p in P)== 2-({p}<P). Mais vous devrez alors modifier votre saisie en {8,29,47,48,49}:)
JBernardo

21

TI-BASIC, 96 octets (87 pour entrée non concurrente)

Pour votre calculatrice graphique de la série TI-84 (!). Ce fut tout un défi, car il n'y a pas moyen facile d'écrire une routine graphique en mémoire tampon (certainement rien construit), et l'écran graphique ne comporte que quatre commandes graphiques pertinentes: Pxl-On(), Pxl-Off(), Pxl-Change(), et pxl-Test().

Utilise tous les pixels accessibles à l’écran et s’enveloppe correctement. Chaque cellule correspond à un pixel et le programme met à jour ligne par ligne horizontalement vers la droite de l'écran. Étant donné que les calculatrices ne disposent que d’un processeur z80 à 15 MHz et que BASIC est un langage interprété lentement, le code ne reçoit qu’une image toutes les cinq minutes environ.

La saisie utilisateur est simple: avant d’exécuter le programme, utilisez l’outil Plume pour dessiner votre forme sur l’écran du graphique.

Adapté de mon inscription à un concours de golf sur le forum de la calculatrice Omnimaga .

0
While 1
For(X,0,94
Ans/7+49seq(pxl-Test(remainder(Y,63),remainder(X+1,95)),Y,62,123
For(Y,0,62
If 1=pxl-Test(Y,X)+int(3fPart(3cosh(fPart(6ֿ¹iPart(sum(Ans,Y+1,Y+3
Pxl-Change(Y,X
End
End
End

Version Omnimaga (87 octets)

Ce code a une fonctionnalité supplémentaire: il détecte s'il est exécuté pour la première fois et aléatoirement l'état de l'écran. Lors des exécutions suivantes, la simulation se poursuit automatiquement si elle est arrêtée à la fin d'une image. Toutefois, il ne s’agit pas d’une entrée concurrente car elle n’enroule pas l’écran; les cellules sur la bordure extérieure seront toujours considérées comme mortes si l'écran du graphique est préalablement effacé.

0
While 1
For(X,0,93
Ans/7+49seq(pxl-Test(Y,X+1),Y,0,62
For(Y,1,61
If 2rand>isClockOn=pxl-Test(Y,X)+int(3fPart(3cosh(fPart(6ֿ¹iPart(sum(Ans,Y,Y+2
Pxl-Change(Y,X
End
End
ClockOff
End

Cette version est probablement le code le plus golfé que j'ai jamais écrit, et contient quelques optimisations vraiment méchantes:

  • J'utilise l'état d'horloge comme un drapeau. Au début du programme, la date / heure est activée et j'utilise la valeur de l'indicateur global isClockOn pour déterminer s'il s'agit de la première itération. Une fois la première image dessinée, je ferme l'horloge. Enregistre un octet sur la méthode la plus courte et environ quatre sur la méthode évidente.

  • Je stocke les états des trois colonnes à côté de celle qui est mise à jour dans un tableau de 63 éléments en nombre en base 7. La place du 49 tient la colonne à droite, celle du 7 la colonne du milieu et la place des unités la colonne de gauche - 1 pour une cellule vivante et 0 pour une cellule morte. Ensuite, je prends le reste mod 6 de la somme des trois nombres autour de la cellule en cours de modification pour trouver le nombre total de cellules voisines vivantes (c'est comme la divisibilité par 9 astuce - en base 7, le reste mod 6 est égal à la somme de les chiffres). Enregistre environ 10 octets par lui-même et donne la possibilité d'utiliser les deux optimisations suivantes. Exemple de diagramme (supposons qu’il existe un planeur centré sur une certaine colonne à Y = 45:

    Row # | Cell State       | Stored number | Mod 6 = cell count
    ...
    44      Live, Live, Live   49+7+1 = 57     3
    45      Dead, Dead, Live   49+0+0 = 49     1
    46      Dead, Live, Dead   0+7+0  = 7      1
    ...
    

    La cellule centrale restera morte car elle est entourée d’exactement cinq cellules vivantes.

  • Une fois chaque ligne complétée, les nombres du tableau sont mis à jour en divisant les nombres existants par 7, en supprimant la partie décimale et en ajoutant 49 fois les valeurs des cellules de la nouvelle colonne. Le stockage des trois colonnes à chaque fois serait beaucoup plus lent et moins élégant, prenez au moins 20 octets supplémentaires et utilisez trois listes au lieu d'une, car les valeurs des cellules de chaque ligne doivent être stockées avant la mise à jour des cellules. C’est de loin le moyen le plus simple de stocker les positions des cellules.

  • L'extrait int(3fPart(3cosh(donne 1lorsque l'entrée est égale à 3/6, 2lorsqu'elle est égale à 4/6 et 0lorsqu'elle est égale à 0, 1/6, 2/6 ou 5/6. Économise environ 6 octets.


19

Mathematica - 333

Fonctionnalités:

  • Interface interactive: cliquez sur les cellules pour créer vos motifs

  • Belle grille

  • Boutons: RUN, PAUSE, CLEAR

Le code est ci-dessous.

Manipulate[x=Switch[run,1,x,2,CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},{2,2,2}}},
{1,1}},x],3,Table[0,{k,40},{j,40}]];EventHandler[Dynamic[tds=Reverse[Transpose[x]];
ArrayPlot[tds,Mesh->True]],{"MouseClicked":>(pos=Ceiling[MousePosition["Graphics"]];
x=ReplacePart[x,pos->1-x[[Sequence@@pos]]];)}],{{run,3,""},{1->"||",2->">",3->"X"}}]

entrez la description de l'image ici

Si vous voulez avoir une idée de la façon dont cela fonctionne, le deuxième exemple de ce blog est simplement une version plus élaborée (analyse en direct de Fourier, meilleure interface) du code ci-dessus. L'exemple devrait fonctionner directement dans votre navigateur après le téléchargement du plugin gratuit.


2
+1, sympa pour s'essayer. Ouais c'est le problème avec ce site, il y a des tonnes de vieilles questions que l'on a tendance à rater.
Griffin

@Griffin merci de l'avoir remarqué;)
Vitaliy Kaurov

15

C 1063 caractères

En tant que défi, j’ai fait cela en C en utilisant l’API Windows non favorable au golf pour des E / S en temps réel. Si le verrouillage est activé, la simulation sera exécutée. Il restera immobile si Capslock est désactivé. Dessiner des motifs avec la souris; clic gauche ravive les cellules et clic droit tue les cellules.

#include <windows.h>
#include<process.h>
#define K ][(x+80)%20+(y+80)%20*20]
#define H R.Event.MouseEvent.dwMousePosition
#define J R.Event.MouseEvent.dwButtonState
HANDLE Q,W;char*E[3],O;Y(x,y){return E[0 K;}U(x,y,l,v){E[l K=v;}I(){E[2]=E[1];E[1]=*E;*E=E[2];memset(E[1],0,400);}A(i,j,k,l,P){while(1){Sleep(16);for(i=0;i<20;++i)for(j=0;j<20;++j){COORD a={i,j};SetConsoleCursorPosition(Q,a);putchar(E[0][i+j*20]==1?'0':' ');}if(O){for(i=0;i<20;++i)for(j=0;j<20;++j){for(k=i-1,P=0;k<i+2;++k)for(l=j-1;l<j+2;++l){P+=Y(k,l);}U(i,j,1,P==3?1:Y(i,j)==1&&P==4?1:0);}I();}}}main(T,x,y,F,D){for(x=0;x<21;++x)puts("#####################");E[0]=malloc(800);E[1]=E[0]+400;I();I();W=GetStdHandle(-10);Q=GetStdHandle(-11);SetConsoleMode(W,24);INPUT_RECORD R;F=D=O=0;COORD size={80,25};SetConsoleScreenBufferSize(Q,size);_beginthread(A,99,0);while(1){ReadConsoleInput(W,&R,1,&T);switch(R.EventType){case 1:O=R.Event.KeyEvent.dwControlKeyState&128;break;case 2:switch(R.Event.MouseEvent.dwEventFlags){case 1:x=H.X;y=H.Y;case 0:F=J&1;D=J&2;}if(F)U(x,y,0,1);if(D)U(x,y,0,0);}}}

Le fichier EXE compilé peut être trouvé ici

Edit: j'ai commenté la source. C'est disponible ici


J'aimerais voir une version commentée de cela!
luser droog

1
Bien sûr, si je me souviens de ce que je pensais ... = p
Kaslai

1
@luserdroog Ici c'est pastebin.com/BrX6wgUj
Kaslai

C'est juste génial.
rayryeng

12

J (39 caractères)

l=:[:+/(3 4=/[:+/(,/,"0/~i:1)|.])*.1,:]

Basé sur cette version APL (même algorithme, convolution toroïdale).

Exemple d'utilisation:

   r =: (i.3 3) e. 1 2 3 5 8
   r
0 1 1          NB. A glider!
1 0 1
0 0 1

   R =: _1 _2 |. 5 7 {. r
   R
0 0 0 0 0 0 0  NB. Test board
0 0 0 1 1 0 0
0 0 1 0 1 0 0
0 0 0 0 1 0 0
0 0 0 0 0 0 0

   l R
0 0 0 0 0 0 0  NB. Single step
0 0 0 1 1 0 0
0 0 0 0 1 1 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0

10

Mathematica, 123 caractères

Une implémentation très rudimentaire qui n'utilise pas la fonction intégrée CellularAutomaton de Mathematica.

ListAnimate@NestList[ImageFilter[If[3<=Total@Flatten@#<=3+#[[2]][[2]],1,0]&,#,1]&,Image[Round/@RandomReal[1,{200,200}]],99]

8

Ruby 1.9 + SDL (380 325 314)

EDIT : 314 caractères, et correction d'un bug avec des cellules supplémentaires apparaissant en vie à la première itération. Augmentation de la taille de la grille à 56 car la routine de couleur ne considère que les 8 bits les plus bas.

EDIT : Golf jusqu'à 325 caractères. La largeur / hauteur de la grille est maintenant de 28 puisque 28 * 9 est la plus grande que vous puissiez avoir tout en utilisant la valeur comme couleur d’arrière-plan. De plus, il ne traite plus qu’un seul événement SDL par itération, ce qui évite complètement la boucle interne. Assez serré je pense!

La simulation commence en pause et toutes les cellules sont mortes. Vous pouvez appuyer sur n’importe quelle touche pour basculer en pause ou en pause, puis cliquer sur n’importe quelle cellule pour la faire basculer entre vivante et morte. Effectue une itération tous les dixièmes de seconde.

L'emballage est un peu insipide.

require'sdl'
SDL.init W=56
R=0..T=W*W
b=[]
s=SDL::Screen.open S=W*9,S,0,0
loop{r="#{e=SDL::Event.poll}"
r['yU']?$_^=1:r[?Q]?exit: r['nU']?b[e.y/9*W+e.x/9]^=1:0
b=R.map{|i|v=[~W,-W,-55,-1,1,55,W,57].select{|f|b[(i+f)%T]}.size;v==3||v==2&&b[i]}if$_
R.map{|i|s.fillRect i%W*9,i/W*9,9,9,[b[i]?0:S]*3}
s.flip
sleep 0.1}

Ressemble à ça:

Capture d'écran de l'application en action

Défi amusant! Je me félicite des améliorations que tout le monde peut voir.


Bien essayé mais je vois tout de suite que tu as mal tourné. Vous ne pouvez pas avoir un tel schéma dans GoL. Ayez une autre lecture des règles: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
Griffin

@Griffin Je pense que la capture d'écran a été prise après une pause et le basculement manuel de certaines cellules. Je vérifierai cependant à nouveau les règles. Merci!
Paul Prestidge

7
@Griffin le modèle de semences ne peut-il avoir aucune configuration possible?
ardnew

7

Scala, 1181 1158 1128 1063 1018 1003 999 992 987 caractères

import swing._
import event._
object L extends SimpleSwingApplication{import java.awt.event._
import javax.swing._
var(w,h,c,d,r)=(20,20,20,0,false)
var x=Array.fill(w,h)(0)
def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
def top=new MainFrame with ActionListener{preferredSize=new Dimension(500,500)
menuBar=new MenuBar{contents+=new Menu("C"){contents+={new MenuItem("Go/Stop"){listenTo(this)
reactions+={case ButtonClicked(c)=>r= !r}}}}}
contents=new Component{listenTo(mouse.clicks)
reactions+={case e:MouseClicked=>var p=e.point
x(p.x/c)(p.y/c)^=1
repaint}
override def paint(g:Graphics2D){for(j<-0 to h-1;i<-0 to w-1){var r=new Rectangle(i*c,j*c,c,c)
x(i)(j)match{case 0=>g draw r
case 1=>g fill r}}}}
def actionPerformed(e:ActionEvent){if(r){var t=x.map(_.clone)
for(j<-0 to h-1;i<-0 to w-1){d=0
n(i,j)
x(i)(j)match{case 0=>if(d==3)t(i)(j)=1
case 1=>if(d<2||d>3)t(i)(j)=0}}
x=t.map(_.clone)
repaint}}
val t=new Timer(200,this)
t.start}}

Ungolfed:

import swing._
import event._

object Life extends SimpleSwingApplication
{
    import java.awt.event._
    import javax.swing._
    var(w,h,c,d,run)=(20,20,20,0,false)
    var x=Array.fill(w,h)(0)
    def n(y:Int,z:Int)=for(b<-z-1 to z+1;a<-y-1 to y+1 if(!(a==y&&b==z)))d+=x((a+w)%w)((b+h)%h)
    def top=new MainFrame with ActionListener
    {
        title="Life"
        preferredSize=new Dimension(500,500)
        menuBar=new MenuBar
        {
            contents+=new Menu("Control")
            {
                contents+={new MenuItem("Start/Stop")
                {
                    listenTo(this)
                    reactions+=
                    {
                        case ButtonClicked(c)=>run= !run
                    }
                }}
            }
        }
        contents=new Component
        {
            listenTo(mouse.clicks)
            reactions+=
            {
                case e:MouseClicked=>
                    var p=e.point
                    if(p.x<w*c)
                    {
                        x(p.x/c)(p.y/c)^=1
                        repaint
                    }
            }
            override def paint(g:Graphics2D)
            {
                for(j<-0 to h-1;i<-0 to w-1)
                {
                    var r=new Rectangle(i*c,j*c,c,c)
                    x(i)(j) match
                    {
                        case 0=>g draw r
                        case 1=>g fill r
                    }
                }
            }
        }
        def actionPerformed(e:ActionEvent)
        {
            if(run)
            {
                var t=x.map(_.clone)
                for(j<-0 to h-1;i<-0 to w-1)
                {
                    d=0
                    n(i,j)
                    x(i)(j) match
                    {
                        case 0=>if(d==3)t(i)(j)=1
                        case 1=>if(d<2||d>3)t(i)(j)=0
                    }
                }
                x=t.map(_.clone)
                repaint
            }
        }
        val timer=new Timer(200,this)
        timer.start
    }
}

La plus grande partie du code ici est du matériel d'interface graphique Swing. Le jeu lui-même est dans la actionPerformedméthode qui est déclenchée par le Timer, et la fonction d'assistance nqui compte les voisins.

Usage:

Compilez-le avec scalac filenamepuis lancez-le scala L.
En cliquant sur un carré, il passe de la vie à la mort, et l'option de menu démarre et arrête la partie. Si vous souhaitez modifier la taille de la grille, modifiez les trois premières valeurs de la ligne: var(w,h,c,d,r)=(20,20,20,0,false)il s'agit respectivement de la largeur, de la hauteur et de la taille de la cellule (en pixels).


J'ai trouvé 2 améliorations au golf: import java.awt.event._et contents+=m("Go",true)+=m("Stop",false)}}menant à 1093 caractères.
utilisateur inconnu

@utilisateur inconnu Merci. J'ai moi-même trouvé quelques améliorations - jusqu'à 1063 maintenant.
Gareth

Zut vous avez été occupé. Continuez! Je testerai les réponses lorsque quelques personnes les publieront.
Griffin

7

Pure Bash, 244 octets

Fonctionne sur un univers 36x24 à enveloppe toroïdale:

mapfile a
for e in {0..863};{
for i in {0..8};{
[ "${a[(e/36+i/3-1)%24]:(e+i%3-1)%36:1}" == O ]&&((n++))
}
d=\ 
c=${a[e/36]:e%36:1}
[ "$c" == O ]&&((--n==2))&&d=O
((n-3))||d=O
b[e/36]+=$d
n=
}
printf -vo %s\\n "${b[@]}"
echo "$o"
exec $0<<<"$o"

Puisqu'il s'agit d'un script shell, la méthode d'entrée est conforme aux autres commandes shell - c'est-à-dire depuis stdin:

$ ./conway.sh << EOF

   O 
    O 
  OOO 

EOF


  O O                                                       
   OO                                                       
   O                                                        

















    O                                                       
  O O                                                       
   OO                                                       

... etc

Nous pouvons rediriger les entrées de n’importe quelle source de texte, via un trfiltre pour obtenir des générations initiales intéressantes, par exemple:

man tr | tr [:alnum:] O | ./conway.sh

6

JavaScript, 130

Pas tout à fait à la hauteur du défi, mais pour l’instant, voici un moteur Game of Life de 130 octets fabriqué par Subzey et moi en 2013.

http://xem.github.io/miniGameOfLife/

/* Fill an array with 0's and 1's, and call g(array, width, height) to iterate */
g=function(f,c,g,d,e,b,h){g=[];e=[c+1,c,c-1,1];for(b=c*c;b--;g[b]=3==d||f[b]&&2==d,d=0)for(h in e)d+=f[b+e[h]]+f[b-e[h]];return g}

Cela semble avoir quelques problèmes avec la première rangée. Par exemple, réglage @@\n@@(carré 2 sur 2 dans le coin supérieur gauche) ou .@\n.@\n.@. (Colonne 1 par 3)
Annan

5

C # - 675 caractères

J'ai toujours voulu écrire une version de ce programme. Je ne savais jamais que cela ne prendrait qu'une demi-heure de paresse pour une version rapide et sale. (Le golf prend beaucoup plus de temps, bien sûr.)

using System.Windows.Forms;class G:Form{static void Main(){new G(25).ShowDialog();}
public G(int z){var g=new Panel[z,z];var n=new int [z,z];int x,y,t;for(int i=0;i<z;
i++)for(int j=0;j<z;j++){var p=new Panel{Width=9,Height=9,Left=i*9,Top=j*9,BackColor
=System.Drawing.Color.Tan};p.Click+=(s,a)=>p.Visible=!p.Visible;Controls.Add(g[i,j]=
p);}KeyUp+=(s,_)=>{for(int i=0;i<99;i++){for(x=0;x<z;x++)for(y=0;y<z;y++){t=0;for(int 
c=-1;c<2;c++)for(int d=-1;d<2;d++)if(c!=0||d!=0){int a=x+c,b=y+d;a=a<0?24:a>24?0:a;b=
b<0?24:b>24?0:b;t+=g[a,b].Visible?0:1;}if(t==3||t>1&&!g[x,y].Visible)n[x,y]=1;if(t<2
||t>3)n[x,y]=0;}for(x=0;x<z;x++)for(y=0;y<z;y++)g[x,y].Visible=n[x,y]<1;Update();}};}}

Usage

  • Entrez un motif de départ en cliquant sur les cellules pour les activer (en vie).
  • Démarrez le jeu en appuyant sur n’importe quelle touche du clavier.
  • Le jeu dure 99 générations à chaque pression sur une touche (j'aurais pu faire 9 pour sauver un personnage, mais cela semblait trop boiteux).

Compromis de golf

  • Vous pouvez seulement activer les cellules avec la souris, pas les éteindre, donc si vous faites une erreur, vous devez redémarrer le programme.
  • Il n'y a pas de lignes de grille, mais cela ne nuit pas trop à la jouabilité.
  • La vitesse de mise à jour est proportionnelle à la vitesse du processeur. Par conséquent, sur les ordinateurs très rapides, il sera probablement flou.
  • Les cellules vivantes sont rouges parce que "noir" utilise 2 caractères supplémentaires.
  • La petitesse des cellules et le fait qu'elles n'utilisent pas tout l'espace du formulaire sont également des compromis qui préservent le caractère.

5

GW-BASIC, 1086 1035 octets (en jetons)

Sous forme symbolisée, il s'agit de 1035 octets. (Le formulaire ASCII est bien sûr un peu plus long.) Vous obtenez le formulaire à jeton en utilisant la SAVE"lifecommande sans ajout ",adans l'interpréteur.

10 DEFINT A-Z:DEF SEG=&HB800:KEY OFF:COLOR 7,0:CLS:DEF FNP(X,Y)=PEEK((((Y+25)MOD 25)*80+((X+80)MOD 80))*2)
20 X=0:Y=0
30 LOCATE Y+1,X+1,1
40 S$=INKEY$:IF S$=""GOTO 40
50 IF S$=CHR$(13)GOTO 150
60 IF S$=" "GOTO 130
70 IF S$=CHR$(0)+CHR$(&H48)THEN Y=(Y-1+25)MOD 25:GOTO 30
80 IF S$=CHR$(0)+CHR$(&H50)THEN Y=(Y+1)MOD 25:GOTO 30
90 IF S$=CHR$(0)+CHR$(&H4B)THEN X=(X-1+80)MOD 80:GOTO 30
100 IF S$=CHR$(0)+CHR$(&H4D)THEN X=(X+1)MOD 80:GOTO 30
110 IF S$="c"THEN CLS:GOTO 20
120 GOTO 40
130 Z=PEEK((Y*80+X)*2):IF Z=42 THEN Z=32ELSE Z=42
140 POKE(Y*80+X)*2,Z:GOTO 40
150 LOCATE 1,1,0:ON KEY(1)GOSUB 320:KEY(1) ON
160 V!=TIMER+.5:FOR Y=0 TO 24:FOR X=0 TO 79:N=0
170 Z=FNP(X-1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
180 Z=FNP(X,Y-1):IF Z=42 OR Z=46 THEN N=N+1
190 Z=FNP(X+1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
200 Z=FNP(X-1,Y):IF Z=42 OR Z=46 THEN N=N+1
210 Z=FNP(X+1,Y):IF Z=42 OR Z=46 THEN N=N+1
220 Z=FNP(X-1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
230 Z=FNP(X,Y+1):IF Z=42 OR Z=46 THEN N=N+1
240 Z=FNP(X+1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
250 Z=PEEK((Y*80+X)*2):IF Z=32 THEN IF N=3 THEN Z=43
260 IF Z=42 THEN IF N<2 OR N>3 THEN Z=46
270 POKE(Y*80+X)*2,Z:NEXT:NEXT:FOR Y=0 TO 24:FOR X=0 TO 79:Z=PEEK((Y*80+X)*2):IF Z=46 THEN Z=32
280 IF Z=43 THEN Z=42
290 POKE(Y*80+X)*2,Z:NEXT:NEXT
300 IF TIMER<V!GOTO 300
310 IF INKEY$=""GOTO 160
320 SYSTEM

C'est la version avec maximum de golf, mais elle est toujours fonctionnelle: au démarrage, vous obtenez un éditeur dans lequel vous pouvez vous déplacer avec les touches du curseur; espace active / désactive les bactéries sur le champ actuel, cefface l'écran, retourne en mode de jeu.

Suit une version moins obscurcie, qui définit également un tableau de jeu initial avec deux structures (une chose en rotation circulaire et un planeur):

1000 REM Conway's Game of Life
1001 REM -
1002 REM Copyright (c) 2012 Thorsten "mirabilos" Glaser
1003 REM All rights reserved. Published under The MirOS Licence.
1004 REM -
1005 DEFINT A-Z:DEF SEG=&hB800
1006 KEY OFF:COLOR 7,0:CLS
1007 DEF FNP(X,Y)=PEEK((((Y+25) MOD 25)*80+((X+80) MOD 80))*2)
1010 PRINT "Initial setting mode, press SPACE to toggle, RETURN to continue"
1020 PRINT "Press C to clear the board, R to reset. OK? Press a key then."
1030 WHILE INKEY$="":WEND
1050 CLS
1065 DATA 3,3,4,3,5,3,6,3,7,3,8,3,3,4,4,4,5,4,6,4,7,4,8,4
1066 DATA 10,3,10,4,10,5,10,6,10,7,10,8,11,3,11,4,11,5,11,6,11,7,11,8
1067 DATA 11,10,10,10,9,10,8,10,7,10,6,10,11,11,10,11,9,11,8,11,7,11,6,11
1068 DATA 4,11,4,10,4,9,4,8,4,7,4,6,3,11,3,10,3,9,3,8,3,7,3,6
1069 DATA 21,0,22,1,22,2,21,2,20,2,-1,-1
1070 RESTORE 1065
1080 READ X,Y
1090 IF X=-1 GOTO 1120
1100 POKE (Y*80+X)*2,42
1110 GOTO 1080
1120 X=0:Y=0
1125 LOCATE Y+1,X+1,1
1130 S$=INKEY$
1140 IF S$="" GOTO 1130
1150 IF S$=CHR$(13) GOTO 1804
1160 IF S$=" " GOTO 1240
1170 IF S$=CHR$(0)+CHR$(&h48) THEN Y=(Y-1+25) MOD 25:GOTO 1125
1180 IF S$=CHR$(0)+CHR$(&h50) THEN Y=(Y+1) MOD 25:GOTO 1125
1190 IF S$=CHR$(0)+CHR$(&h4B) THEN X=(X-1+80) MOD 80:GOTO 1125
1200 IF S$=CHR$(0)+CHR$(&h4D) THEN X=(X+1) MOD 80:GOTO 1125
1210 IF S$="c" THEN CLS:GOTO 1120
1220 IF S$="r" GOTO 1050
1225 IF S$=CHR$(27) THEN END
1230 GOTO 1130
1240 Z=PEEK((Y*80+X)*2)
1250 IF Z=42 THEN Z=32 ELSE Z=42
1260 POKE (Y*80+X)*2,Z
1270 GOTO 1130
1804 LOCATE 1,1,0
1900 ON KEY(1) GOSUB 2300
1910 KEY(1) ON
2000 V!=TIMER+.5
2010 FOR Y=0 TO 24
2020  FOR X=0 TO 79
2030   N=0
2040   Z=FNP(X-1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
2050   Z=FNP(X  ,Y-1):IF Z=42 OR Z=46 THEN N=N+1
2060   Z=FNP(X+1,Y-1):IF Z=42 OR Z=46 THEN N=N+1
2070   Z=FNP(X-1,Y  ):IF Z=42 OR Z=46 THEN N=N+1
2080   Z=FNP(X+1,Y  ):IF Z=42 OR Z=46 THEN N=N+1
2090   Z=FNP(X-1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
2100   Z=FNP(X  ,Y+1):IF Z=42 OR Z=46 THEN N=N+1
2110   Z=FNP(X+1,Y+1):IF Z=42 OR Z=46 THEN N=N+1
2120   Z=PEEK((Y*80+X)*2)
2130   IF Z=32 THEN IF N=3 THEN Z=43
2140   IF Z=42 THEN IF N<2 OR N>3 THEN Z=46
2150   POKE (Y*80+X)*2,Z
2160  NEXT X
2170 NEXT Y
2200 FOR Y=0 TO 24
2210  FOR X=0 TO 79
2220   Z=PEEK((Y*80+X)*2)
2230   IF Z=46 THEN Z=32
2240   IF Z=43 THEN Z=42
2250   POKE (Y*80+X)*2,Z
2260  NEXT X
2270 NEXT Y
2280 IF TIMER<V! GOTO 2280
2290 IF INKEY$="" GOTO 2000
2300 SYSTEM

J'ai écrit ceci en 15 minutes en m'ennuyant et en attendant un ami qui jouait du code-golf avec son «apprenti» pour Game of Life de Conway en même temps.

Cela fonctionne comme ceci: Il utilise immédiatement le tampon d’écran en mode texte 80x25 (changez l’initiale DEF SEGpour utiliser &hB000si vous êtes sur une carte graphique Hercules; ces paramètres fonctionnent avec Qemu et (plus lent) dosbox). Un astérisque *est une bactérie.

Cela fonctionne en deux passes: premièrement, les lieux de naissance sont marqués +et la mort marque ses cibles .. Dans le second passage, +et .sont remplacés par *et , respectivement.

Le TIMERtruc est de faire attendre une demi-seconde après chaque tour, au cas où votre hôte Qemu serait très rapide

Je n'espère pas le prix le plus court, mais un prix raisonnable, en particulier compte tenu de la configuration initiale du tableau. J'ai aussi une version où le moteur de jeu a été remplacé par le code d'assemblage, au cas où cela vous intéresserait…


Étant donné que vous avez incrémenté vos étiquettes de 1 sur la version sans jeu, est-il possible de faire la même chose sur la version avec jeu? (c.-à 1-d 2. 3,,, etc.) Ou les numéros de ligne ne comptent-ils pas?
Zacharý

les numéros de ligne, lorsqu'ils sont symbolisés, comptent comme un mot (16 bits), si je ne me trompe pas complètement
mirabilos

Bon alors, je suppose que je devais penser à un autre dialecte BASIC.
Zacharý

@ Zacharý Cliquez sur «Format du programme tokenisé GW-BASIC», puis sur «Format du programme» pour voir que, de fait, les numéros de ligne sont toujours deux octets et que le format du jeton est plus détaillé.
mirabilos

5

Mathematica, 115 octets

Voici une échappatoire facile à ceci:

ListAnimate[ArrayPlot/@CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},
{2,2,2}}},{1,1}},{RandomInteger[1,{9,9}],0},90]]

1
Mathematica convient, mais comme le stipulent les règles, le programme doit permettre à l'utilisateur de saisir ses propres modèles. Cette règle est intentionnelle car quelques langues permettent des implémentations courtes comme celle-ci, mais sans interaction de l'utilisateur. Bien sûr, vous pouvez y placer votre propre ensemble, mais cela ne va pas gagner.
Griffin

Dans Mathematica, "l’entrée" se fait principalement via l’interface bloc-notes. Je ne pense donc pas que "l’interaction utilisateur" soit vraiment possible. Il vous suffit de remplacer l'argument RandomInteger de la fonction CellularAutomaton par ce que vous voulez et de réévaluer le code.
JeremyKun

3
L'interaction de l'utilisateur est possible. La méthode la plus simpliste à laquelle je puisse penser maintenant est un tableau de boutons. Donne-lui un homme.
Griffin

4

Java (OpenJDK 8) - 400 388 367 octets

Deuxième et (probablement) Final Edit: Géré au golf 21 octets supplémentaires après la découverte de ces mines (imo) d’ or , il est vivement recommandé à de nouvelles personnes de les lire (en particulier si vous comptez essayer certains de ces défis en utilisant Java).

Le code résultant (va probablement finir par jouer au golf encore plus si je découvre comment raccourcir les boucles doubles imbriquées ...):

u->{int w=u.length,h=u[0].length,x,y,i,j,n;Stack<Point>r=new Stack<Point>();for(;;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x)for(y=0;y<h;++y){boolean o=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}

Essayez-le en ligne!

(Le post original commence ici.)

En fait, j'ai pensé un instant que je pourrais au moins contester la meilleure réponse Python avec ma connaissance (certes limitée) de Java lol ... C’est un défi que j’ai quand même pris plaisir à participer (bien que j’ai rejoint le parti un peu en retard ...)

Il n'y a pas grand-chose à cela vraiment - explication de base comme suit (non-golfé):

/*
 * Explanation of each variable's usage:
 * w=height* of array
 * h=width* of array
 * x=y* coord of point in array
 * y=x* coord of point in array
 * i and j are counters for calculating the neighbours around a point in the array
 * n=neighbour counter
 * r=temporary array to store the cells from the current generation
 * u=the 2d array used for all the calculations (parameter from lambda expression)
 * c=temporary variable used to help populate the 2d array
 * o=boolean variable that stores the value of whether the cell is alive or not
 */
u-> // start of lambda statement with u as parameter (no need for brackets as it's only one parameter being passed)
{
    int w=u.length,h=u[0].length,x,y,i,j,n; // defines all the necessary integer variables;
    Stack<Point>r=new Stack<Point>(); // same with the only array list needed (note how I only use two data structures);
    for(;;) // notice how this is still an infinite loop but using a for loop;
    {
        for(Point c:r)u[c.x][c.y]=1; //for every point in the "previous" generation, add that to the 2D array as a live (evil?) cell;
        r.clear(); // clears the array list to be populated later on
        for(x=0;x<w;++x) // a pair of nested for loops to iterate over every cell of the 2D array;
        {
            for(y=0;y<h;++y)
            {
                // sets o to be the presence of a live cell at (x,y) then uses said value in initialising the neighbour counter;
                boolean o=u[x][y]>1;n=o?-1:0;
                for(i=-2;++i<2;) // another pair of nested for loops - this one iterates over a 3x3 grid around *each* cell of the 2D array;
                {                // this includes wrap-around (note the modulus sign in the if statement below);
                    for(j=-2;++j<2;)
                    {
                        if(u[(w+x+i)%w][(h+y+j)%h]>0)++n; // this is where the first interesting thing lies - the bit which makes wrap-around a reality;
                    }
                }
                if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y)); // this is the second interesting bit of my code - perhaps more so as I use bitwise operators to calculate the number of neighbours (x,y) has;
                                                            // (since I'm technically dealing with 0s and 1s, it's not a total misuse of them imo);
                System.out.print(u[x][y]+(y>h-2?"\n":""));  // that extra part of the print statement adds a newline if we reached the end of the current 'line';
            }
        }
        // since the information about the new generation is now in the array list, this array can be emptied out, ready to receive said info on the new generation;
        for(int[]t:u)Arrays.fill(t,0);
    }
} // end of lambda statement

(plus d'informations sur les instructions lambda dans Java 8 ici )

Oui, il y a un problème avec mon approche.

Comme la plupart d’entre vous l’a probablement remarqué, le code que je joue au golf dans sa version actuelle fera une boucle pour toujours. Pour éviter cela, un compteur peut être introduit en haut et utilisé dans la boucle while pour n'afficher que n(dans ce cas, 5) les itérations comme suit (notez la nouvelle bvariable ajoutée):

u->{int b=0,w=u.length,h=u[0].length,x,y,i,j,n;Stack<Point>r=new Stack<Point>();for(;++b<6;){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x)for(y=0;y<h;++y){boolean o=u[x][y]>0;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]>0)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]+(y>h-2?"\n":""));}for(int[]t:u)Arrays.fill(t,0);}}

De plus, quelques points méritent d’être mentionnés. Ce programme ne vérifie pas si l'entrée est correcte et échouera donc avec (très probablement) un ArrayOutOfBoundsException; en tant que tel, assurez-vous de vérifier que l'entrée est valide en remplissant complètement une partie d'un tableau (les tableaux en brochettes renverront l'exception mentionnée ci-dessus). De plus, le tableau actuel semble «fluide», c'est-à-dire qu'il n'y a pas de séparation entre les générations. Si vous souhaitez ajouter cela pour vérifier que les générations produites sont bien valides, System.out.println();vous devez en ajouter un avant for(int[]t:u)Arrays.fill(t,0);(voir la section Essayez-le en ligne! Pour plus de clarté). Et dernier point, mais non le moindre, étant donné qu'il s'agit de mon premier code golf, tout commentaire est grandement apprécié :)

Ancien code de la réponse précédente de 388 octets:

u->{int w=u.length,h=u[0].length,x,y,i,j,n;ArrayList<Point>r=new ArrayList<Point>();while(true){for(Point c:r)u[c.x][c.y]=1;r.clear();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}for(int[]t:u)Arrays.fill(t,0);}}

Et à partir de la réponse initiale de 400 octets:

int w=35,h=20,x,y,i,j,n;ArrayList<Point>l=new ArrayList<Point>(),r;while(true){int[][]u=new int[w][h];for(Point c:l)u[c.x][c.y]=1;r=new ArrayList<Point>();for(x=0;x<w;++x){for(y=0;y<h;++y){boolean o=u[x][y]==1;n=o?-1:0;for(i=-2;++i<2;)for(j=-2;++j<2;)if(u[(w+x+i)%w][(h+y+j)%h]==1)++n;if(o&n>1&n<4|!o&n==3)r.add(new Point(x,y));System.out.print(u[x][y]);}System.out.println();}l.clear();l.addAll(r);}

Amazing first post, bienvenue chez PPCG!
Zacharý

Merci, je vais certainement en faire plus - ils sont amusants :)
NotBaal

Rejoignez-nous, nous avons Dennis. En outre, ce n'est pas un programme complet ni une fonction, ce qui doit être, IIRC.
Zacharý

Oh, oui, j'ai oublié la partie 'programme': P Modifier cela dans un instant.
NotBaal

Cela peut juste être une fonction aussi.
Zacharý

4

Pochoir , 6 octets

Pas ma langue préférée, mais il est court ...

4 octets de code plus les indicateurs nlist et Torus.

3me

Essayez-le en ligne!

Est ...
3 3
 membre
m du m oore-quartier-comte avec soi ou
e la lande e -neighbourhood-comte sans moi
...?


3

Scala - 799 caractères

Exécuter en tant que script. Un clic de souris sur un carré permet de l'activer ou de le désactiver et n'importe quelle touche démarre ou arrête la génération.

import java.awt.Color._
import swing._
import event._
import actors.Actor._
new SimpleSwingApplication{var(y,r,b)=(200,false,Array.fill(20,20)(false))
lazy val u=new Panel{actor{loop{if(r){b=Array.tabulate(20,20){(i,j)=>def^(i:Int)= -19*(i min 0)+(i max 0)%20
var(c,n,r)=(0,b(i)(j),-1 to 1)
for(x<-r;y<-r;if x!=0||y!=0){if(b(^(i+x))(^(j+y)))c+=1}
if(n&&(c<2||c>3))false else if(!n&&c==3)true else n}};repaint;Thread.sleep(y)}}
focusable=true
preferredSize=new Dimension(y,y)
listenTo(mouse.clicks,keys)
reactions+={case e:MouseClicked=>val(i,j)=(e.point.x/10,e.point.y/10);b(i)(j)= !b(i)(j)case _:KeyTyped=>r= !r}
override def paintComponent(g:Graphics2D){g.clearRect(0,0,y,y);g.setColor(red)
for(x<-0 to 19;y<-0 to 19 if b(x)(y))g.fillRect(x*10,y*10,9,9)}}
def top=new Frame{contents=u}}.main(null)

3

J, 45

Je pensais que j'essaierais J Ce n'est pas encore très bien joué au golf, mais je vais essayer encore une fois.

(]+.&(3&=)+)+/((4&{.,(_4&{.))(>,{,~<i:1))&|.

Exemple:

   f =: 5 5 $ 0 1 0 0 0   0 0 1 0 0   1 1 1 0 0   0 0 0 0 0    0 0 0 0 0
   f
0 1 0 0 0
0 0 1 0 0
1 1 1 0 0
0 0 0 0 0
0 0 0 0 0
   f (]+.&(3&=)+)+/((4&{.,(_4&{.))(>,{,~<i:1))&|. f
0 0 0 0 0
1 0 1 0 0
0 1 1 0 0
0 1 0 0 0
0 0 0 0 0

3

Traitement 536 532

int h=22,t=24,i,j;int[][]w=new int[t][t],b=new int[t][t];int[]q={1,0,-1};void draw(){if(t<9){clear();for(i=2;i<h;i++){for(j=2;j<h;j++)w[i][j]=b[i][j];w[i][1]=w[i][21];w[i][h]=w[i][2];w[1][i]=w[21][i];w[h][i]=w[2][i];}for(i=1;i<23;i++)for(j=1;j<23;j++){t=-w[i][j];for(int s:q)for(int d:q)t+=w[i+s][j+d];b[i][j]=w[i][j]>0&(t<2|t>3)?0:t==3?1:b[i][j];}a();}}void keyPressed(){t=0;}void mousePressed(){int i=mouseX/5+2,j=mouseY/5+2;w[i][j]=b[i][j]=1;a();}void a(){for(i=0;i<h-2;i++)for(j=0;j<h-2;j++)if(w[i+2][j+2]==1)rect(i*5,j*5,5,5);}

Je crois que cela satisfait à toutes les exigences.

Ungolfed:

int h=22,t=24,i,j;
int[][]w=new int[t][t],b=new int[t][t];
int[]q={1,0,-1};
void draw(){
  if(t<9){
  clear();
  for(i=2;i<h;i++){
    for(j=2;j<h;j++)
      w[i][j]=b[i][j];  
    w[i][1]=w[i][21];
    w[i][h]=w[i][2];
    w[1][i]=w[21][i];
    w[h][i]=w[2][i];
  }
  for(i=1;i<23;i++)
    for(j=1;j<23;j++){
      t=-w[i][j];
      for(int s:q)
        for(int d:q)
          t+=w[i+s][j+d];        
      b[i][j]=w[i][j]>0&(t<2|t>3)?0:t==3?1:b[i][j];  
  }
  a();
}
}
void keyPressed(){
  t=0;
}
void mousePressed(){
  int i=mouseX/5+2,j=mouseY/5+2;
  w[i][j]=b[i][j]=1;
  a();
}
void a(){
  for(i=0;i<h-2;i++)
    for(j=0;j<h-2;j++)
      if(w[i+2][j+2]==1)
        rect(i*5,j*5,5,5);
  }  

3

Matlab (152)

b=uint8(rand(20)<0.2)
s=@(m)imfilter(m,[1 1 1;1 0 1;1 1 1],'circular')
p=@(m,n)uint8((n==3)|(m&(n==2)))
while 1
imshow(b)
drawnow
b=p(b,s(b))
end

Je n'ai pas installé Matlab pour le tester, je viens de jouer au code que j'ai écrit il y a quelques années.
Ungolfed:

%% initialize
Bsize = 20;
nsteps = 100;
board = uint8(rand(Bsize)<0.2); % fill 20% of the board
boardsum = @(im) imfilter(im,[1 1 1; 1 0 1; 1 1 1], 'circular');
step = @(im, sumim) uint8((sumim==3) | (im & (sumim==2)) );

%% run
for i = 1:nsteps
    imshow(kron(board,uint8(ones(4))), [])
    drawnow
    ss(p,i) = sum(board(:));
    board = step(board, boardsum(board));
end
  • Boardsize est codé en dur mais peut être n'importe quoi
  • s'enroule autour
  • pour une entrée utilisateur, on peut changer la carte initiale en codant en dur une autre matrice ou en utilisant l’éditeur de variables. Ce n'est pas beau, mais ça marche
  • 20 caractères peuvent être enregistrés si la sortie graphique est ignorée, le tableau sera toujours imprimé sous forme de texte à chaque itération. Les cellules d'un pixel qui changent chaque milliseconde ne sont de toute façon pas très utiles

fonctionne dans R2014a, vient de tester
masterX244

3

Perl, 218 216 211 202 octets

$,=$/;$~=AX3AAAx76;$b=pack('(A79)23',<>)x6;{print unpack'(a79)23a0',$b;select$v,$v,$v,0.1;$b=pack'(A)*',unpack'((x7a/(x13)X4Ax!18)1817@0)4',pack'((a*)17xx!18)*',unpack"x1737(AA$~Ax$~AA$~@)2222",$b;redo}

(Pas de nouvelle ligne à la fin de ce code.)

Lit le modèle de départ à partir de l'entrée standard, sous la forme d'un fichier texte dans lequel les cellules vivantes sont représentées 1, les cellules mortes sont représentées sous la forme d'un espace, les lignes étant séparées par une nouvelle ligne. L'entrée ne doit pas avoir de caractères autres que ceux-là. Les lignes peuvent être de longueur variable et seront complétées ou tronquées à exactement 79 cm de large. Exemple d'entrée est un canon de planeur:

                                  1
                                1 1
                      11      11            11
                     1   1    11            11
          11        1     1   11
          11        1   1 11    1 1
                    1     1       1
                     1   1
                      11









                                         11
                                         1
                                          111
                                            1

Lorsque le programme exécute Game of Life, chaque état est transféré dans la sortie standard dans un format similaire à celui de l'entrée, puis retarde 0,1 seconde. Le délai peut être personnalisé en modifiant le quatrième argument de l'appel sélectionné.

Le plateau de jeu est codé en dur à la taille 79x23. Il est enveloppé dans un tore: si vous laissez la planche en bas, vous vous retrouvez en haut; si vous partez du côté droit, vous vous retrouvez du côté gauche mais décalé d’une rangée vers le bas.

Voici une autre version qui ne lit aucune entrée et qui part d'un tableau aléatoire:

$,=$/;$/=AX3AAAx76;$b=pack("(A)*",map{rand 3<1}0..1816)x6;{print unpack'(a79)23a0',$b;select$v,$v,$v,0.1;$b=pack'(A)*',unpack'((x7a/(x13)X4Ax!18)1817@0)4',pack'((a*)17xx!18)*',unpack"x1737(AA$/Ax$/AA$/@)2222",$b;redo}

Ce code est dérivé d' un programme de jeu Perl obfusqué que j'ai écrit il y a des années . Je l'ai beaucoup changé pour que la planche soit toroïdale et que le code soit reconnu.

Ce n'est probablement pas la méthode la plus courte pour implémenter Game of Life en perl, mais c'est l'une des moins compréhensibles.

Le tableau est stocké $bsous forme de chaîne '1'et ' ', une pour chaque cellule, seul le tout est répété au moins trois fois. Le troisième appel de décompression extrait 17 valeurs pour chaque cellule: une pour la cellule elle-même et deux pour chacune des huit cellules voisines, dans un ordre arbitraire, et chaque valeur est '1'une chaîne vide. La cellule doit être active à la prochaine itération si le nombre de '1'valeurs parmi ces 17 valeurs est 5, 6 ou 7. Le troisième appel de pack concatène ces 17 valeurs en un champ de 18 caractères de largeur aligné à gauche et complété avec zéro octet à droite. . Le second appel de décompression prend un tel champ large, dépêche sur le caractère en position 7, décompresse l’espace à partir de la position 17 si c’est un'1', ou déballe le caractère de la position 4 sinon. Ce résultat est exactement la valeur que la cellule devrait avoir dans la prochaine génération.


2

Python, 589 octets

Boutons de la souris: gauche - mettre une cellule, droite - supprimer une cellule, milieu - démarrer / arrêter.

de Tkinter import *
copie d'importation
z = plage
F = 50
T = Tk ()
S = 9
f = [F * [0] pour i in'7 '* F]
c = toile (T, largeur = S * F, hauteur = S * F)
c.pack ()
def p (x, y, a): f [y] [x] = f [y] [x] ou c.create_oval (x * S, y * S, x * S + S, y * S + S) si un autre c.delete (f [y] [x])
r = 1
def R (e): global r; r = 1-r
exec ("c.bind ('<Button-% i>', lambda e: p (ex / S, ey / S,% i));" * 2% (1,1,3,0))
c.bind ('<Button-2>', R)
def L ():
 T.after (99, L)
 si r: retour
 g = copy.deepcopy (f)
 pour y dans z (F):
	pour x dans z (F):
	 n = 8
	 pour j dans z (-1,2):
		pour i dans z (-1,2):
		 si i ou j: n- = pas g [(y + j)% F] [(x + i)% F]
	 si 1 <n <4:
		si n == 3 et non g [y] [x]: p (x, y, 1)
	 sinon: p (x, y, 0)
L ()
T.mainloop ()

Et voici une version où vous pouvez faire glisser la souris pour dessiner. Les graphismes sont un peu plus agréables.

from Tkinter import*
import copy
z=range
F=50
T=Tk()
S=9
f=[F*[0]for i in'7'*F]
c=Canvas(T,bg='white',width=S*F,height=S*F)
c.pack()
def p(x,y,a):f[y][x]=f[y][x]or c.create_rectangle(x*S,y*S,x*S+S,y*S+S,fill='gray')if a else c.delete(f[y][x])
r=1
def R(e):global r;r=1-r
exec("c.bind('<Button-%i>',lambda e:p(e.x/S,e.y/S,%i));c.bind('<B%i-Motion>',lambda e:p(e.x/S,e.y/S,%i));"*2%(1,1,1,1,3,0,3,0))
c.bind('<Button-2>',R)
def L():
 T.after(99,L)
 if r:return
 g=copy.deepcopy(f)
 for y in z(F):
  for x in z(F):
   n=8
   for j in z(-1,2):
    for i in z(-1,2):
     if i or j:n-=not g[(y+j)%F][(x+i)%F]
   if 1<n<4:
    if n==3and not g[y][x]:p(x,y,1)
   else:p(x,y,0)
L()
T.mainloop()

Cela ne suit pas correctement les règles du jeu de la vie.
Steven Rumbalski

1
@StevenRumbalski: Oh vraiment?
Oleh Prypin

2
vraiment. Vous avez une erreur d'indentation dans votre deuxième version. La section commençant par if 1<n<4:devrait être en retrait au même niveau quefor j in z(-1,2):
Steven Rumbalski

2

Python 2, 456 octets

Bien que je sache qu'il s'agit d'un ancien post, je ne pouvais m'empêcher de tenter le coup. Le tableau initial peut être de n'importe quelle taille, à condition de tracer une bordure autour de lui et de laisser un espace supplémentaire sur la dernière ligne.

Golf.py

import time,itertools as w,sys;t,q=map(lambda x:list(x[:-1]),sys.stdin.readlines()),list(w.product(range(-1,2),range(-1,2)));del q[4];n=map(lambda x:x[:],t[:])
while time.sleep(0.1)==None:
 for j in range(1,len(t)-1):
  for i in range(1,len(t[j])-1):x=sum(map(lambda s:1 if t[j+s[0]][i+s[1]]in'@'else 0,q));f=t[j][i];n[j][i]='@'if(f=='@'and(x==3 or x==2))or(f==' 'and x==3)else' '
 t=map(lambda x:x[:],n[:]);print'\n'.join(list(map(lambda x:''.join(x),t)))

Input.txt (notez l'espace supplémentaire sur la dernière ligne)

+----------------------------------------+
|                    @                   |
|                     @                  |
|                   @@@                  |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
|                                        |
+----------------------------------------+ 

Comment courir

python Golf.py < input.txt

time.sleep(0.1)==None=> not time.sleep(.1), (f=='@'and(x==3 or x==2)) ou (f == '' et x == 3) =>x==3or f=='@'and x==2
CalculatorFeline le

^, Vous en avez oublié un, 1 if=> 1if.
Zacharý

2

En traitement 270 261 249 octets

La grille correspond aux 100 * 100 pixels d’écran, l’entrée se présente sous la forme d’une image png

void setup(){image(loadImage("g.png"),0,0);}void draw(){loadPixels();int n,i=0,j,l=10000;int[]a=new int[l],p=pixels;for(;i<l;a[i]=n==5?-1<<24:n==6?p[i]:-1,i++)for(j=n=0;j<9;j++)n+=j!=4?p[(i+l-1+j%3+100*(j/3-1))%l]&1:0;arrayCopy(a,p);updatePixels();}

Ungolfed

void setup() {
  image(loadImage("g.png"), 0, 0);
}
void draw() {
  loadPixels();
  int c=100, i=0, n, l=c*c, b=color(0);
  int[]a=new int[l], p=pixels;
  for (; i<l; i++) {
    n=p[(i+l-101)%l]&1;
    n+=p[(i+l-100)%l]&1;
    n+=p[(i+l-99)%l]&1;
    n+=p[(i+l-1)%l]&1;
    n+=p[(i+1)%l]&1;
    n+=p[(i+99)%l]&1;
    n+=p[(i+100)%l]&1;
    n+=p[(i+101)%l]&1;
    a[i]=n==5?b:p[i]==b&&n==6?b:-1;
  }
  arrayCopy(a, pixels, l);
  updatePixels();
}

capture d'écran


2

Lua + LÖVE / Love2D , 653 octets

l=love f=math.floor t={}s=25 w=20 S=1 for i=1,w do t[i]={}for j=1,w do t[i][j]=0 end end e=0 F=function(f)loadstring("for i=1,#t do for j=1,#t[i]do "..f.." end end")()end function l.update(d)if S>0 then return end e=e+d if e>.2 then e=0 F("c=0 for a=-1,1 do for b=-1,1 do if not(a==0 and b==0)then c=c+(t[((i+a-1)%w)+1][((j+b-1)%w)+1]>0 and 1 or 0)end end end g=t[i][j]t[i][j]=(c==3 or(c==2 and g==1))and(g==1 and 5 or-1)or(g==1 and 4 or 0)")F("t[i][j]=t[i][j]%2")end end function l.draw()F("l.graphics.rectangle(t[i][j]==1 and'fill'or'line',i*s,j*s,s,s)")end function l.mousepressed(x,y)S=0 o,p=f(x/s),f(y/s)if t[o]and t[o][p]then t[o][p]=1 S=1 end end

ou espacés:

l=love
f=math.floor
t={}s=25
w=20
S=1
for i=1,w do
    t[i]={}
    for j=1,w do
        t[i][j]=0
    end
end
e=0
F=function(f)
    loadstring("for i=1,#t do for j=1,#t[i] do  "..f.." end end")()
end
function l.update(d)
    if S>0 then
        return
    end
    e=e+d
    if e>.2 then
        e=0
        F([[
        c=0
        for a=-1,1 do
            for b=-1,1 do
                if not(a==0 and b==0)then
                    c=c+(t[((i+a-1)%w)+1][((j+b-1)%w)+1]>0 and 1 or 0)
                end
            end
        end
        g=t[i][j]
        t[i][j]=(c==3 or(c==2 and g==1))and(g==1 and 5 or-1) or (g==1 and 4 or 0)]])
        F("t[i][j]=t[i][j]%2")
    end
end
function l.draw()
    F("l.graphics.rectangle(t[i][j]==1 and'fill'or'line',i*s,j*s,s,s)") end
function l.mousepressed(x,y)
    S=0
    o,p=f(x/s),f(y/s)
    if t[o]and t[o][p] then
        t[o][p]=1
        S=1
    end
end

Cliquez sur le champ pour ajouter des cellules vivantes. Cliquez en dehors du champ pour l'exécuter.

Essayez-le en ligne!

entrez la description de l'image ici


1

Postscript 529 515

Commencé avec l'exemple de Rosetta Code . Invoquez avec un argument filename ( gs -- gol.ps pulsar), le fichier contenant 20 * 20 nombres binaires (séparés par un espace). Boucle infinie: dessinez un tableau, attendez pour entrer, calculez la prochaine génération.

[/f ARGUMENTS 0 get(r)file/n 20>>begin[/m
n 1 sub/b[n{[n{f token pop}repeat]}repeat]/c 400
n div/F{dup 0 lt{n add}if dup n ge{n sub}if}>>begin{0
1 m{dup 0 1 m{2 copy b exch get exch get 1 xor setgray
c mul exch c mul c c rectfill dup}for pop pop}for
showpage/b[0 1 m{/x exch def[0 1 m{/y exch def 0
y 1 sub 1 y 1 add{F dup x 1 sub 1 x
1 add{F b exch get exch get 3 2 roll add exch
dup}for pop pop}for b x get y get sub b x get y get
0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq
or{1}{0}ifelse}ifelse}for]}for]def}loop

Espacé, avec quelques commentaires de pile (juste ceux dont j'avais besoin).

[
/f ARGUMENTS 0 get(r)file
/n 20
/sz 400
%/r{rand 2147483647 div}
>>begin
[
/m n 1 sub
/b[
%n{[n{r .15 le{1}{0}ifelse}repeat]}repeat
 n{[n{f token pop}repeat]}repeat
]
/c sz n div
/F{dup 0 lt{n add}if dup n ge{n sub}if}
>>begin
{
    0 1 m{dup % y y
    0 1 m{ % y y x
        2 copy b exch get exch get 1 xor setgray
        c mul exch c mul c c rectfill
        dup 
    }for pop pop}for
    pstack
    showpage
    /b[0 1 m{/x exch def
      [0 1 m{/y exch def
          0   
          y 1 sub 1 y 1 add{F dup %s y y
          x 1 sub 1 x 1 add{F %s y y x
              b exch get exch get %s y bxy
              3 2 roll add exch %s+bxy y
              dup %s y y
          }for pop pop}for
          b x get y get sub
          b x get y get
          0 eq{3 eq{1}{0}ifelse}{dup 2 eq exch 3 eq or{1}{0}ifelse}ifelse
      }for]
      }for]def
}loop

fichier de données pulsar:

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 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 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 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 1 1 1 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 1 1 1 0 0 0 1 1 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 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 1 1 1 0 0 0 1 1 1 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 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

1

JavaScript 676

Désolé Griffin, je ne pouvais tout simplement pas regarder votre code et ne pas le réécrire légèrement ... je devais me débarrasser de deux personnages, mais ça en valait la peine!

b=[];r=c=s=20;U=document;onload=function(){for(z=E=0;z<c;++z)for(b.push(t=[]),j=0;j<r;j++)with(U.body.appendChild(U.createElement("button")))t.push(0),id=z+"_"+j,style.position="absolute",style.left=s*j+"px",style.top=s*z+"px",onclick=a}; ondblclick=function(){A=E=E?clearInterval(A):setInterval(function(){Q=[];for(z=0;z<c;++z){R=[];for(j=0;j<r;)W=(c+z-1)%c,X=(c+z+1)%c,Y=(r+j-1)%r,Z=(r+j+1)%r,n=b[W][Y]+b[z][Y]+b[X][Y]+b[W][j]+b[X][j]+b[W][Z]+b[z][Z]+b[X][Z],R.push(b[z][j++]?4>n&&1<n:3==n);Q.push(R)}b=Q.slice();d()})};function a(e){E?0:P=e.target.id.split("_");b[P[0]][P[1]]^=1;d()}function d(){for(z=0;z<c;++z)for(j=0;j<r;)U.getElementById(z+"_"+j).innerHTML=b[z][j++]-0}

Mais comme on dit, il est plus facile de demander pardon que la permission ...;)


1

Octave (153)

la même chose que Matlab de DenDenDo au jeu le plus court de la vie , mais a dû être immédiatement modifiée en imagesc:

b=uint8(rand(20)<0.2)
s=@(m)imfilter(m,[1 1 1;1 0 1;1 1 1],'circular')
p=@(m,n)uint8((n==3)|(m&(n==2)))
while 1
imagesc(b)
drawnow
b=p(b,s(b))
end

1

Python 2: 334 octets

Seulement 6 ans de retard.

import time
s='';s=map(list,iter(raw_input,s));k=len(s);l=(-1,0,1);n=int;z=range
while 1:
 r=[[0]*k for i in z(k)]
 for i in z(k*k):
  a,b=i//k,i%k
  m,g=sum([n(s[(a+c)%k][(b+d)%k])for c in l for d in l if c|d]),n(s[a][b])
  r[a][b]=n((m==2)&g or m==3)
  print'*'if r[a][b]else' ',
  if b-k+1==0:print
 s=r;time.sleep(.2);print"\033c"

Vous pouvez le lancer comme:

python gol.py
0000000
0001000
0000100
0011100
0000000
0000000
0000000

Là où les 0 et les 1 représentent des cellules mortes et vivantes, une nouvelle ligne à la fin commence l'exécution.

Les grilles doivent être carrées.

Il est plus facile à exécuter que le plus petit python, prend en charge les grilles de toutes tailles et est joli à l'exécution.

C'est aussi 100 octets de plus, donc ça y est.


0

PHP, 201 octets (non testé)

for($s=file(f);print"\n";$s=$t)foreach($s as$y=>$r)for($x=-print"
";"
"<$c=$s[$y][++$x];print$t[$y][$x]=" X"[$n<4&$n>2-$a])for($n=-$a=$c>A,$i=$x-!!$x-1;$i++<=$x;)for($k=$y-2;$k++<=$y;)$n+=$s[$k][$i]>A;

Courez avec -nr.

panne

for($s=file(f);                         # import input from file "f"
    print"\n";                              # infinite loop: 1. print newline
    $s=$t)                                  # 3. copy target to source, next iteration
    foreach($s as$y=>$r)                    # 2. loop through lines
        for($x=-print"\n";"\n"<$c=$s[$y][++$x]; # print newline, loop $x/$c through line characters (before line break)
            print                                   # 5. print new cell
                $t[$y][$x]=" X"[$n>2-$a&$n<4])      # 4. new cell is alive if neighbour count<4 and >2 (>1 if alive)
            for($n=-                                # 2. init neighbour count: exclude self
                $a=$c>A,                            # 1. $a=cell is alife
                $i=$x-!!$x-1;$i++<=$x;)             # 3. loop $i from one left to one right of current position
                for($k=$y-2;$k++<=$y;)                  # loop $k from one above to one below current position
                    $n+=$s[$k][$i]>A;                       # increase neighbor count if neighbour is alife
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.