Il gioco più breve della vita


59

Conway's Game of Life è il classico esempio di automazione cellulare. Le celle formano una griglia quadrata e ognuna ha due stati: vivo o morto. Ad ogni turno, ogni cella si aggiorna contemporaneamente in base al suo stato e a quelli dei suoi otto vicini:

  • Una cellula viva rimane viva se ha esattamente due o tre vicini vivi
  • Una cellula morta diventa viva se ha esattamente tre vicini vivi

La tua missione, se scegli di accettarla, è codificare la più breve implementazione di Game of Life nella tua lingua preferita.

Le regole:

  • La griglia deve essere almeno 20x20
  • La griglia deve avvolgere (quindi la griglia è come la superficie di un toro)
  • L'implementazione deve consentire all'utente di inserire i propri schemi di partenza
  • GoL è un po 'inutile se non riesci a vedere cosa sta succedendo, quindi deve esserci un output visivo dell'automa in esecuzione, con il risultato di ogni turno mostrato per il tempo necessario per essere visto!

8
Precedentemente su Stack Overflow: Code Golf: Conway's Game of Life , e assicurati di guardare il link di implementazione APL nei commenti.
dmckee,

1
Ah, non l'ho visto. Ma questo è leggermente diverso no (salvami eliminando il lavoro mettendo insieme la sfida?
Griffin

6
Non è un problema. Molti puzzle già in esecuzione su Stack Overflow sono stati fatti anche qui, ma la gente ti dirà che sono ossessivo sul collegamento a sfide simili.
dmckee,

@Griffin: puoi rimuoverli tutti ;prima di }s. Inoltre varè possibile eliminare a volte s (se non si rompe il codice). E per una linea fors, ifs, ecc, è possibile eliminare il { }tutto: for(...) for(...) dosomething().
pimvdb,

@pimvdb, evviva, non l'ho ancora completamente giocato a golf, non ho avuto il tempo. volevo solo dimostrare che ci provavo anch'io, piuttosto che porre pigramente una sfida. Lo golf al massimo presto.
Griffin,

Risposte:


27

HTML5 Canvas con JavaScript, 940 639 586 519 caratteri

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

Ho sempre voluto fare qualcosa con la tela, quindi ecco il mio tentativo (versione originale online ). Puoi attivare o disattivare le celle facendo clic su (anche possibile in modalità di esecuzione).

Ora puoi anche provare la nuova versione qui .

Sfortunatamente c'è un problema che non ho ancora potuto risolvere. La versione online è più lunga di 11 caratteri perché jsFiddle inserisce un nodo di testo appena prima dell'area di disegno (perché?) E quindi l'area di disegno non è più il primo figlio.

Modifica 1: molte ottimizzazioni e ristrutturazioni.

Modifica 2: diverse piccole modifiche.

Modifica 3: Inline il blocco di script completo più modifiche minori.


Bello, ma cambia il ritardo dell'intervallo per 1renderlo più veloce del mio piuttosto che di quel passo lento. Inoltre, se si desidera implementare il disegno (anziché fare clic su ciascun quadrato), è possibile arrotondare la posizione del mouse alla dimensione del blocco più vicina e riempire il rettangolo in quel punto. Più personaggi ma più punti.
Griffin,

È possibile sostituire new Array('#FFF','#800')con ['#FFF','#800'].
Lowjacker

Anche se lo dico sul disegno, il mio super golf non permette il disegno ed è brutto come il peccato. Haha. È possibile impostare i due colori snell'array su tane redpoiché sono i due colori con le rappresentazioni più brevi, consente di risparmiare due caratteri. Inoltre, se possibile, inserisci la versione letterale di jnell'intervallo. Sono sicuro che c'è anche molto altro da spremere.
Griffin,

@Griffin e Lowjacker: grazie mille. Sono anche abbastanza sicuro che puoi giocare a golf molto di più (e hai già qualche idea). Purtroppo non ho trovato il tempo di farlo. Domani seguirà una versione migliore del golf - spero ...
Howard,

2
Puoi rimuovere i tag html e body. Funzionerà allo stesso modo
intorno

32

Python, 219 caratteri

Sono andato per il massimo golfage, con un'interfaccia sufficiente per soddisfare la domanda.

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)

Lo esegui in questo modo:

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

I numeri nell'elenco rappresentano le coordinate delle celle iniziali. La prima riga è 0-19, la seconda riga è 20-39, ecc.

Eseguilo in un terminale con 21 file e sembra piuttosto elegante.


1
Questo avrebbe dovuto assolutamente vincere. Immagino che la "facilità di input" sia stata ponderata abbastanza in alto.
primo

@primo Mi spingerei persino al punto di suggerire a mma di avere una competizione separata.
Luser droog,

2
Allora è questa vita di Py?
Christopher Wirt,

Puoi sempre salvare un altro carattere ... 2-(p in P)== 2-({p}<P). Ma poi dovresti cambiare il tuo input in {8,29,47,48,49}:)
JBernardo il

21

TI-BASIC, 96 byte (87 per ingressi non concorrenti)

Per la tua calcolatrice grafica serie TI-84 (!). Questa è stata una vera sfida, perché non esiste un modo semplice per scrivere una routine grafica tamponata (assolutamente niente di costruito in), e lo schermo grafico ha solo quattro comandi grafici rilevanti: Pxl-On(), Pxl-Off(), Pxl-Change(), e pxl-Test().

Utilizza tutti i pixel accessibili sullo schermo e si avvolge correttamente. Ogni cella è un pixel e il programma si aggiorna riga per riga orizzontalmente a destra attraverso lo schermo. Poiché i calcolatori hanno solo un processore z80 a 15 MHz e BASIC è un linguaggio interpretato lentamente, il codice ottiene solo un frame ogni cinque minuti.

L'input dell'utente è semplice: prima di eseguire il programma, usa lo strumento Penna per disegnare la tua forma sullo schermo del grafico.

Adattato dal mio ingresso a una gara di golf nel forum di calcolatori 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

Versione Omnimaga (87 byte)

Questo codice ha una funzione aggiuntiva: rileva se viene eseguito per la prima volta e se randomizza lo stato dello schermo. Nelle corse successive continua automaticamente la simulazione se interrotta al termine di un fotogramma. Tuttavia, non è una voce in competizione perché non avvolge lo schermo; le celle sul bordo esterno saranno sempre considerate morte se lo schermo del grafico viene cancellato in anticipo.

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

Questa versione è probabilmente il codice più golfato che io abbia mai scritto, e contiene alcune ottimizzazioni offensive davvero brutte:

  • Uso lo stato dell'orologio come una bandiera. All'inizio del programma, l'orologio data / ora è abilitato e utilizzo il valore del flag isClockOn globale per determinare se si tratta della prima iterazione. Dopo aver disegnato il primo fotogramma, spengo l'orologio. Salva un byte sull'altro metodo più breve e circa quattro sul metodo ovvio.

  • Conservo gli stati delle tre colonne accanto a quella che viene aggiornata in una matrice di 63 elementi di numeri base-7. Il posto del 49 tiene la colonna a destra, il posto del 7 tiene la colonna centrale e il posto delle unità contiene la colonna di sinistra - 1 per una cella viva e 0 per una cella morta. Quindi prendo il resto mod 6 della somma dei tre numeri attorno alla cella modificata per trovare il numero totale di celle vicine vive (è proprio come la divisibilità per 9 trucco - nella base 7, il resto mod 6 è uguale alla somma di le cifre). Salva circa 10 byte da solo e offre l'opportunità di utilizzare le successive due ottimizzazioni. Diagramma di esempio (supponiamo che ci sia un aliante centrato su una determinata colonna in 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 cellula centrale rimarrà morta, perché è circondata esattamente da cinque cellule vive.

  • Dopo aver completato ogni riga, i numeri nell'array vengono aggiornati dividendo i numeri esistenti per 7, scartando la parte decimale e aggiungendo 49 volte i valori delle celle nella nuova colonna. Memorizzare tutte e tre le colonne ogni volta sarebbe molto più lento e meno elegante, richiedere almeno 20 byte in più e utilizzare tre elenchi anziché uno, poiché i valori delle celle in ogni riga devono essere memorizzati prima dell'aggiornamento delle celle. Questo è di gran lunga il modo più piccolo per memorizzare le posizioni delle celle.

  • Lo snippet int(3fPart(3cosh(indica 1quando l'ingresso è pari a 3/6, 2quando è uguale a 4/6 e 0quando è uguale a 0, 1/6, 2/6 o 5/6. Salva circa 6 byte.


19

Mathematica - 333

Caratteristiche:

  • Interfaccia interattiva: fai clic sulle celle per creare i tuoi schemi

  • Bella griglia

  • Pulsanti: RUN, PAUSE, CLEAR

Il codice è sotto.

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"}}]

inserisci qui la descrizione dell'immagine

Se vuoi avere un'idea di come funziona, il secondo esempio in questo blog è solo una versione più elaborata (analisi di Fourier live, migliore interfaccia) del codice sopra. L'esempio dovrebbe essere eseguito direttamente nel browser dopo il download gratuito del plugin.


2
+1, bello per provare. Sì, questo è il problema con questo sito, ci sono tonnellate di vecchie domande che si tende a perdere.
Griffin,

@Griffin grazie per averlo notato;)
Vitaliy Kaurov,

15

C 1063 caratteri

Come sfida, l'ho fatto in C usando l'API di Windows ostile al golf per l'IO in tempo reale. Se il maiuscolo è attivo, la simulazione verrà eseguita. Rimarrà immobile se il blocco maiuscole è disattivato. Disegna motivi con il mouse; il clic sinistro fa rivivere le celle e il tasto destro uccide le celle.

#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);}}}

Il file EXE compilato è disponibile qui

Modifica: ho commentato la fonte. È disponibile qui


Mi piacerebbe vedere una versione commentata di questo!
Luser droog

1
Certo, se ricordo cosa stavo pensando ... = p
Kaslai,

1
@luserdroog Eccolo pastebin.com/BrX6wgUj
Kaslai

Questo è semplicemente fantastico.
rayryeng - Ripristina Monica il

12

J (39 caratteri)

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

Basato su questa versione APL (stesso algoritmo, convoluzione toroidale).

Esempio di utilizzo:

   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 caratteri

Un'implementazione molto rudimentale che non utilizza la funzione CellularAutomaton integrata di 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 caratteri, e risolto un bug con celle extra che apparivano vivi alla prima iterazione. Aumentato la dimensione della griglia a 56 poiché la routine del colore esamina solo gli 8 bit più bassi.

EDIT : golfato fino a 325 caratteri. La larghezza / altezza della griglia ora è 28 poiché 28 * 9 è il più grande che puoi avere mentre usi ancora il valore come colore di sfondo. Inoltre elabora ora solo un evento SDL per iterazione, che elimina completamente il ciclo interno. Abbastanza stretto, penso!

La simulazione inizia in pausa, con tutte le celle morte. Puoi premere qualsiasi tasto per attivare / disattivare la pausa / pausa e fare clic su qualsiasi cella per alternare tra vivo e morto. Esegue un'iterazione ogni decimo di secondo.

La confezione è un po 'traballante.

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}

Somiglia a questo:

Schermata dell'app in azione

Sfida divertente! Accolgo con favore tutti i miglioramenti che chiunque può vedere.


Bel tentativo ma vedo subito che hai sbagliato. Non puoi avere uno schema simile in GoL. Leggi di nuovo le regole: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
Griffin

@Griffin Penso che lo screenshot sia stato preso dopo aver messo in pausa e attivato alcune celle manualmente, ma controllerò di nuovo le regole. Grazie!
Paul Prestidge,

7
@Griffin non può essere il modello seme in qualsiasi configurazione possibile?
Ardnew,

7

Scala, 1181 1158 1128 1063 1018 1003 999 992 987 caratteri

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 parte più grande del codice qui è roba della GUI di Swing. Il gioco stesso è nel actionPerformedmetodo che è attivato dalla Timerfunzione di aiuto e nche conta i vicini.

Uso:

Compilalo con scalac filenamee poi eseguilo scala L.
Facendo clic su un quadrato, lo si passa da vivo a morto e l'opzione di menu avvia e interrompe il gioco. Se vuoi cambiare la dimensione della griglia, cambia i primi tre valori nella linea: var(w,h,c,d,r)=(20,20,20,0,false)sono rispettivamente larghezza, altezza e dimensione della cella (in pixel).


Ho trovato 2 miglioramenti del golf: import java.awt.event._e contents+=m("Go",true)+=m("Stop",false)}}, portando a 1093 caratteri.
utente sconosciuto

@utente sconosciuto Grazie. Ho trovato alcuni miglioramenti da solo - fino al 1063 ora.
Gareth,

Accidenti sei stato occupato. Continuate così! Metterò alla prova le risposte quando poche altre persone le pubblicheranno.
Griffin,

7

Pure Bash, 244 byte

Funziona su un universo 36x24 avvolto toroidalmente:

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"

Poiché si tratta di uno script di shell, il metodo di input è congruente con altri comandi di shell, ovvero da stdin:

$ ./conway.sh << EOF

   O 
    O 
  OOO 

EOF


  O O                                                       
   OO                                                       
   O                                                        

















    O                                                       
  O O                                                       
   OO                                                       

... eccetera

Possiamo reindirizzare l'input da qualsiasi sorgente di testo, reindirizzato attraverso un trfiltro per ottenere interessanti generazioni iniziali, ad es

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

6

JavaScript, 130

Non rispondendo totalmente alla sfida, ma per la cronaca, ecco un motore di Game of Life in 130 byte realizzato da Subzey e io nel 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}

Questo sembra avere alcuni problemi con la prima riga. Ad esempio l'impostazione @@\n@@(2 per 2 quadrati nell'angolo in alto a sinistra) o .@\n.@\n.@. (Colonna 1 per 3)
Annan,

5

C # - 675 caratteri

Ho sempre desiderato scrivere una versione di questo programma. Non ho mai saputo che ci sarebbe voluta solo una pigra mezz'ora per una versione veloce e sporca. (Il golf richiede molto più tempo, ovviamente.)

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();}};}}

uso

  • Immettere un modello iniziale facendo clic sulle celle per attivarle (attive).
  • Inizia il gioco premendo un tasto qualsiasi della tastiera.
  • Il gioco funziona per 99 generazioni ogni volta che si preme un tasto (avrei potuto farlo 9 per salvare un personaggio, ma sembrava troppo zoppo).

Compromessi del golf

  • Puoi accendere le celle solo con il mouse, non spento, quindi se commetti un errore devi riavviare il programma.
  • Non ci sono linee della griglia, ma ciò non danneggia troppo la giocabilità.
  • La velocità di aggiornamento è proporzionale alla velocità della CPU, quindi su computer molto veloci sarà probabilmente solo una sfocatura.
  • Le celle viventi sono rosse perché "nero" utilizza altri 2 caratteri.
  • La piccolezza delle celle e il fatto che non consumano tutto lo spazio della forma sono anche compromessi per il risparmio di carattere.

5

GW-BASIC, 1086 1035 byte (tokenizzato)

In forma tokenizzata, si tratta di 1035 byte. (Il modulo ASCII è, ovviamente, un po 'più lungo.) È possibile ottenere il modulo tokenizzato utilizzando il SAVE"lifecomando senza aggiungere ",anell'interprete.

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

Questa è la versione con il massimo del golf, ma ancora ricca di funzionalità: all'avvio si ottiene un editor, in cui è possibile spostarsi con i tasti cursore; lo spazio attiva / disattiva i batteri sul campo corrente, ccancella lo schermo, Return avvia la modalità di gioco.

Qui segue una versione meno offuscata, che imposta anche un tabellone iniziale con due strutture (una cosa a rotazione circolare e un aliante):

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

L'ho scritto in 15 minuti mentre mi annoiavo e aspettavo un amico, che stava giocando a golf con il suo "apprendista" per Conway's Game of Life allo stesso tempo.

Funziona in questo modo: usa immediatamente il buffer dello schermo in modalità testo 80x25 (cambia l'iniziale DEF SEGda usare &hB000se sei su una scheda grafica Hercules; queste impostazioni funzionano con Qemu e dosbox (più lento)). Un asterisco *è un batterio.

Funziona in due passaggi: in primo luogo, i luoghi di nascita sono contrassegnati con +e la morte segna i suoi obiettivi con .. Nel secondo passaggio, +e .vengono sostituiti con *e , rispettivamente.

Il TIMERpunto è farlo aspettare mezzo secondo dopo ogni round, nel caso in cui il tuo host Qemu sia molto veloce ☺

Non sto sperando in un prezzo per le vittorie più brevi qui, ma per uno cool, soprattutto considerando la configurazione iniziale della scheda. Ho anche una versione in cui il motore di gioco è stato sostituito dal codice assembly, nel caso tu sia interessato ...


Considerando che hai incrementato le tue etichette di 1 nella versione non golfata, è possibile fare lo stesso con la versione golfata? (vale a dire, 1, 2, 3, ecc) o non i numeri di riga non contano?
Zacharý,

i numeri di riga, quando tokenizzati, contano come parola (16 bit), se non sbaglio totalmente
mirabilos,

Va bene allora, suppongo che dovessi pensare a qualche altro dialetto BASIC allora.
Zacharý,

@ Zacharý Fare clic su "Formato programma tokenizzato GW-BASIC", quindi su "Formato programma" qui per vedere che, in effetti, i numeri di riga sono costantemente due byte e per dettagli più approfonditi sul formato token.
mirabilos,

5

Mathematica, 115 byte

Ecco un semplice cop-out per questo:

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

1
Mathematica va bene, ma come stabilito dalle regole il programma deve consentire all'utente di inserire i propri schemi. Questa regola è intenzionale poiché alcune lingue consentono implementazioni brevi come questa, ma senza interazione da parte dell'utente. Sicuramente puoi mettere il tuo array lì, ma non vincerà.
Griffin,

"input" in Mathematica avviene principalmente attraverso l'interfaccia del notebook, quindi non penso che "l'interazione dell'utente" sia davvero possibile. È sufficiente sostituire l'argomento RandomInteger alla funzione CellularAutomaton con quello che si desidera e rivalutare il codice.
JeremyKun,

3
L'interazione dell'utente è possibile. Il metodo più semplicistico a cui riesco a pensare in questo momento è una serie di pulsanti. Provalo, amico.
Griffin,

4

Java (OpenJDK 8) - 400 388 367 byte

Secondo e (probabilmente) Final Edit: gestito per giocare a golf con 21 byte extra dopo aver trovato queste (imo) miniere d' oro - consiglio vivamente a nuove persone di leggerle (soprattutto se hai intenzione di provare alcune di queste sfide usando Java).

Codice risultante (probabilmente finirà per giocare a golf ancora di più se scoprirò come accorciare quei doppi nidificati per i loop ...):

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);}}

Provalo online!

(Il post originale inizia qui.)

In realtà ho pensato per un momento che sarei stato in grado di sfidare almeno la migliore risposta di Python con la mia (probabilmente discutibile) conoscenza di Java lol ... È stata una sfida che mi è comunque piaciuta partecipare (nonostante sia entrato nella festa, forse solo un un po 'in ritardo ...)

Non c'è molto da fare davvero - spiegazione di base come segue (non golfizzato):

/*
 * 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

(maggiori informazioni sulle dichiarazioni lambda in Java 8 qui )

Sì, c'è un problema con il mio approccio.

Come molti di voi probabilmente hanno notato, il mio codice golfizzato com'è attualmente andrà in loop per sempre. Per evitare ciò, un contatore può essere introdotto nella parte superiore e utilizzato nel ciclo while per visualizzare solo n(in questo caso, 5) iterazioni come segue (notare la nuova bvariabile aggiunta):

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);}}

Inoltre, vale la pena ricordare alcuni punti. Questo programma non controlla se l'ingresso è corretto e, pertanto, fallirà con (molto probabilmente) un ArrayOutOfBoundsException; come tale, assicurarsi di verificare che l'input sia valido compilando completamente una parte di un array (gli array infilzati genereranno l'eccezione sopra menzionata). Inoltre, la scheda così com'è attualmente sembra 'fluida', ovvero non c'è separazione tra una generazione e la successiva. Se desideri aggiungerlo per verificare che le generazioni prodotte siano effettivamente valide, è System.out.println();necessario aggiungere un extra poco prima for(int[]t:u)Arrays.fill(t,0);(vedi questo Provalo online! Per chiarezza). E ultimo, ma non meno importante, dato che questo è il mio primo codice golf, ogni feedback è molto apprezzato :)

Vecchio codice dalla precedente risposta a 388 byte:

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);}}

E dalla risposta iniziale di 400 byte:

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);}

Incredibile primo post, benvenuto in PPCG!
Zacharý,

Grazie, ne farò sicuramente di più - sono divertenti :)
NotBaal il

Unisciti a noi, abbiamo Dennis. Inoltre, questo non è un programma completo né una funzione, che deve essere, IIRC.
Zacharý,

Oh giusto, ho dimenticato la parte "programma": P Modificandolo tra un po '.
NotBaal,

Può anche essere solo una funzione.
Zacharý,

4

Stencil , 6 byte

Non è la mia lingua preferita, ma è breve ...

4 byte di codice più i flag nlist e Torus.

3me

Provalo online!

È ...
3 3
 membro
m del m oore-quartiere-count con sé o
e la brughiera e -neighbourhood-count senza auto
...?


3

Scala - 799 caratteri

Esegui come uno script. Un clic del mouse su un quadrato lo attiva o disattiva e qualsiasi tasto avvia o interrompe la generazione.

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

Ho pensato di provare J. Non è ancora particolarmente ben golfato, ma lo proverò presto di nuovo.

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

Esempio:

   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

Elaborazione 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);}

Credo che questo soddisfi tutti i requisiti.

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

Non ho Matlab installato in questo momento per testarlo, ho appena giocato a golf il codice che ho scritto alcuni anni fa.
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 è hardcoded ma può essere qualsiasi cosa
  • avvolge
  • per l'input dell'utente si può cambiare la scheda iniziale o codificando un'altra matrice o usando l'editor delle variabili. Non carino, ma funziona
  • È possibile salvare 20 caratteri se l'output grafico viene ignorato, la scheda verrà comunque stampata come testo ad ogni iterazione. Le celle a un pixel che cambiano ogni millisecondo non sono comunque molto utili

funziona in R2014a, appena testato
masterX244

3

Perl, 218 216 211 202 byte

$,=$/;$~=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}

(Nessuna nuova riga alla fine di questo codice.)

Legge il modello iniziale dall'input standard, come un file di testo in cui sono rappresentate celle vive come 1, celle morte rappresentate come spazio, le linee sono separate da una nuova riga. L'input non deve avere caratteri diversi da questi. Le linee possono essere di lunghezza variabile e saranno riempite o troncate esattamente a 79 di larghezza. Esempio di input è una pistola aliante:

                                  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

Mentre il programma esegue Game of Life, ogni stato viene scaricato nell'output standard in un formato simile all'input, quindi ritarda 0,1 secondi. Il ritardo può essere personalizzato modificando il quarto argomento della chiamata selezionata.

Il tabellone di gioco è hardcoded alla dimensione 79x23. È avvolto in un toro: se lasci la tavola sul fondo, finisci in cima; se lasci sul lato destro, finisci sul lato sinistro ma ti spostavi di una riga verso il basso.

Ecco una versione alternativa che non legge alcun input e parte da una scheda casuale:

$,=$/;$/=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}

Questo codice deriva da un gioco offuscato del programma di vita perl che ho scritto anni fa . L'ho cambiato molto per rendere la tavola toroidale e il golf il codice.

Questo probabilmente non è il metodo più breve per implementare Game of Life in perl, ma è uno dei meno comprensibili.

La scheda è memorizzata $bcome una stringa di '1'e ' ', una per ogni cella, solo l'intera cosa viene ripetuta almeno tre volte. La terza chiamata di decompressione estrae 17 valori per ogni cella: ce n'è uno per la cella stessa e due per ciascuna delle otto celle vicine, in un ordine arbitrario, e ogni valore è '1'o una stringa vuota. La cella dovrebbe essere attiva nella successiva iterazione se il numero di '1'valori tra questi 17 valori è 5, 6 o 7. La chiamata del terzo pacchetto concatena questi 17 valori in un campo largo 18 caratteri allineato a sinistra e riempito con nul byte a destra . La seconda chiamata di decompressione occupa un campo così ampio di 18, invia il personaggio in posizione 7, disimballa lo spazio dalla posizione 17 se è un'1'o disimballa il personaggio dalla posizione 4 in caso contrario. Questo risultato è esattamente il valore che la cella dovrebbe avere nella prossima generazione.


2

Python, 589 byte

Pulsanti del mouse: sinistra - metti una cella, destra - rimuovi una cella, metà - start / stop.

dall'importazione Tkinter *
copia di importazione
z = gamma
F = 50
T = Tk ()
S = 9
f = [F * [0] per i in'7 '* F]
c = tela (T, larghezza = S * F, altezza = S * F)
c.pack ()
def p (x, y, a): f [y] [x] = f [y] [x] o c.create_oval (x * S, y * S, x * S + S, y * S + S) 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 (ex / S, ey / S,% i));" * 2% (1,1,3,0))
c.bind ( '<Button-2>', R)
def L ():
 T.after (99, L)
 se r: ritorno
 g = copy.deepcopy (f)
 per y in z (F):
	per x in z (F):
	 n = 8
	 per j in z (-1,2):
		per i in z (-1,2):
		 se i o j: n- = non g [(y + j)% F] [(x + i)% F]
	 se 1 <n <4:
		se n == 3e non g [y] [x]: p (x, y, 1)
	 altro: p (x, y, 0)
L ()
T.mainloop ()

Ed ecco una versione in cui è possibile trascinare il mouse per disegnare. La grafica è un po 'più piacevole.

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()

Questo non segue correttamente le regole del gioco della vita.
Steven Rumbalski,

1
@StevenRumbalski: Oh davvero?
Oleh Prypin,

2
veramente. Hai un errore di rientro nella tua seconda versione. La sezione che inizia con if 1<n<4:dovrebbe essere rientrata allo stesso livello difor j in z(-1,2):
Steven Rumbalski il

2

Python 2, 456 byte

Mentre so che questo è un vecchio post, non ho potuto fare a meno di provarlo. La scheda iniziale può avere qualsiasi dimensione purché si tracci un bordo attorno e si disponga di uno spazio aggiuntivo sull'ultima riga.

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 (notare lo spazio extra sull'ultima riga)

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

Come correre

python Golf.py < input.txt

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

^, Ne hai dimenticato uno, 1 if=> 1if.
Zacharý,

2

in lavorazione 270.261 249 byte

La griglia è i 100 * 100 pixel di schermo, l'input si presenta sotto forma di un'immagine 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();
}

immagine dello schermo


2

Lua + LÖVE / Love2D , 653 byte

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

o distanziati:

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

Fai clic sul campo per aggiungere celle viventi. Fare clic all'esterno del campo per eseguirlo.

Provalo online!

inserisci qui la descrizione dell'immagine


1

poscritto 529 515

Iniziato con l'esempio del codice Rosetta . Richiamare con un argomento nomefile ( gs -- gol.ps pulsar), il file contenente 20 * 20 numeri binari (separati da spazio). Ciclo infinito: disegna il tabellone, attendi l'ingresso, calcola la prossima generazione.

[/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

Distanziati, con alcuni commenti in pila (solo quelli di cui avevo bisogno).

[
/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

file di dati 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

Mi dispiace Griffin, non riuscivo a guardare il tuo codice e non a riscriverlo leggermente ... dovevo radere due caratteri ma ne valeva la pena!

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}

Ma come si suol dire, è più facile chiedere perdono che permesso ...;)


1

Ottava (153)

lo stesso di Matlab di DenDenDo a Shortest Game of Life , ma ho dovuto cambiare imshow in 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 byte

Solo 6 anni di ritardo.

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"

Puoi eseguirlo come:

python gol.py
0000000
0001000
0000100
0011100
0000000
0000000
0000000

Laddove gli 0 e 1 rappresentano celle morte e vive, alla fine viene avviata una nuova riga in più.

Le griglie devono essere quadrate.

È più facile da eseguire rispetto a quello più corto di Python, supporta griglie di qualsiasi dimensione e sembra carino quando eseguito.

Sono anche 100 byte in più, quindi c'è quello.


0

PHP, 201 byte (non testato)

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;

Corri con -nr.

abbattersi

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.