El juego más corto de la vida

59

Conway's Game of Life es el ejemplo clásico de automatización celular. Las celdas forman una cuadrícula cuadrada y cada una tiene dos estados: vivo o muerto. En cada turno, cada celda se actualiza simultáneamente según su estado y el de sus ocho vecinos:

  • Una célula viva permanece viva si tiene exactamente dos o tres vecinos vivos.
  • Una célula muerta cobra vida si tiene exactamente tres vecinos vivos.

Su misión, si elige aceptarla, es codificar la implementación más corta de Game of Life en su idioma favorito.

Las normas:

  • La cuadrícula debe ser de al menos 20x20
  • La cuadrícula debe envolverse (por lo que la cuadrícula es como la superficie de un Toro)
  • Su implementación debe permitir al usuario ingresar sus propios patrones de inicio
  • GoL es un poco inútil si no puede ver lo que está sucediendo, por lo que debe haber una salida visual del autómata en funcionamiento, ¡y el resultado de cada turno se mostrará durante el tiempo suficiente para poder verlo!
Grifo
fuente
8
Anteriormente en Stack Overflow: Code Golf: Conway's Game of Life , y asegúrese de mirar el enlace de implementación de APL en los comentarios.
dmckee
1
Ah, no vi eso. Pero esto es un poco diferente, no (¿salvarme de eliminar el trabajo y armar el desafío?
Griffin
66
No es un problema. Muchos acertijos que ya se ejecutan en Stack Overflow también se han hecho aquí, pero la gente te dirá que estoy obsesionado por vincularme a desafíos similares.
dmckee
@Griffin: puede eliminar todos los ;anteriores a }s. También varse pueden eliminar s a veces (si no rompe su código). Y por una línea fors, ifs, etc, se puede eliminar la { }completamente: for(...) for(...) dosomething().
pimvdb
@pimvdb, salud, aún no lo he jugado completamente, no he tenido tiempo. solo quería demostrar que yo también tenía una oportunidad, en lugar de establecer un desafío ociosamente. Lo jugará al máximo pronto.
Griffin

Respuestas:

27

HTML5 Canvas con JavaScript, 940 639 586 519 caracteres

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

Siempre quise hacer algo con el lienzo, así que aquí está mi intento (versión original en línea ). Puede alternar celdas haciendo clic (también es posible en modo de ejecución).

Ahora también puedes probar la nueva versión aquí .

Desafortunadamente, hay un problema que aún no puedo solucionar. La versión en línea tiene 11 caracteres más porque jsFiddle coloca un nodo de texto justo antes del lienzo (¿por qué?) Y, por lo tanto, el lienzo ya no es el primer elemento secundario.

Edición 1: muchas optimizaciones y reestructuraciones.

Edición 2: varios cambios más pequeños.

Edición 3: en línea el bloque de script completo más pequeños cambios.

Howard
fuente
Bien, pero cambiar el intervalo de retraso para 1que sea tan rápido como el mío en lugar de ese paso lento. Además, si desea implementar el dibujo (en lugar de hacer clic en cada cuadrado), puede redondear la posición del mouse al tamaño de bloque más cercano y llenar el rectángulo en ese punto. Más personajes pero más puntos.
Griffin
Se puede reemplazar new Array('#FFF','#800')con ['#FFF','#800'].
Lowjacker
Aunque digo eso sobre dibujar, mi súper golf no permite dibujar y es feo como el pecado. Jaja. Puede configurar sus dos colores en la smatriz tany, reddado que son los dos colores con las representaciones más cortas, le ahorra dos caracteres. Además, si es posible, coloque la versión literal de jen el intervalo. Estoy seguro de que hay mucho más para exprimir también.
Griffin
@ Griffin y Lowjacker: muchas gracias. También estoy bastante seguro de que puedes jugar mucho más al golf (y ya tienes algunas ideas). Lamentablemente no encontré el tiempo para hacerlo. Una versión mejor golfed seguirá mañana - espero ...
Howard
2
Puede eliminar las etiquetas html y body. Funcionará igual
arodebaugh
32

Python, 219 caracteres

Fui por el máximo golfage, con la interfaz suficiente para satisfacer la pregunta.

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 ejecutas así:

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

Los números en la lista representan las coordenadas de las celdas iniciales. La primera fila es 0-19, la segunda fila es 20-39, etc.

Ejecútelo en una terminal con 21 filas y se ve bastante elegante.

Keith Randall
fuente
1
Esto debería haber ganado totalmente. Supongo que la "facilidad de entrada" se ponderó bastante alto.
primo
@primo, incluso llegaría a sugerir que mma debería tener una competencia por separado.
luser droog
2
Entonces, ¿es esta vida de Py?
Christopher Wirt
Siempre puede guardar un carácter más ... 2-(p in P)== 2-({p}<P). Pero entonces tendrías que cambiar tu entrada a {8,29,47,48,49}:)
JBernardo
21

TI-BASIC, 96 bytes (87 para entrada no competitiva)

Para su calculadora gráfica de la serie TI-84 (!). Esto fue todo un reto, ya que no hay manera fácil de escribir una rutina de buffer de gráficos (nada definitivamente incorporada), y la pantalla gráfica tiene sólo cuatro comandos de gráficos pertinentes: Pxl-On(), Pxl-Off(), Pxl-Change(), y pxl-Test().

Utiliza todos los píxeles accesibles en la pantalla y se ajusta correctamente. Cada celda tiene un píxel, y el programa se actualiza línea por línea horizontalmente a la derecha en la pantalla. Debido a que las calculadoras solo tienen un procesador z80 de 15MHz y BASIC es un lenguaje de interpretación lenta, el código solo obtiene una trama cada cinco minutos.

La entrada del usuario es fácil: antes de ejecutar el programa, use la herramienta Pluma para dibujar su forma en la pantalla del gráfico.

Adaptado de mi entrada a un concurso de golf de código en el foro de calculadora 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

Versión Omnimaga (87 bytes)

Este código tiene una característica adicional: detecta si se está ejecutando por primera vez y aleatoriza el estado de la pantalla. En ejecuciones posteriores, continúa automáticamente la simulación si se detiene después de que finaliza un fotograma. Sin embargo, no es una entrada competitiva porque no ajusta la pantalla; las celdas en el borde exterior siempre se considerarán muertas si la pantalla del gráfico se borra de antemano.

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

Esta versión es probablemente el código más avanzado que he escrito, y contiene algunas optimizaciones ofuscadoras realmente desagradables:

  • Yo uso el estado del reloj como una bandera. Al comienzo del programa, el reloj de fecha / hora está habilitado y utilizo el valor del indicador global isClockOn para determinar si es la primera iteración. Después de dibujar el primer cuadro, apago el reloj. Guarda un byte sobre el otro método más corto y aproximadamente cuatro sobre el método obvio.

  • Almaceno los estados de las tres columnas junto a la que se actualiza en una matriz de 63 elementos de números de base 7. El lugar de los 49 mantiene la columna a la derecha, el lugar de los 7 mantiene la columna central y el lugar de las unidades mantiene la columna izquierda: 1 para una celda viva y 0 para una celda muerta. Luego tomo el resto mod 6 de la suma de los tres números alrededor de la celda que se modifica para encontrar el número total de celdas vecinas vivas (es como la divisibilidad por 9 truco; en la base 7, el resto mod 6 es igual a la suma de los dígitos). Ahorra unos 10 bytes por sí mismo y brinda la oportunidad de usar las siguientes dos optimizaciones. Diagrama de ejemplo (digamos que hay un planeador centrado en una determinada columna en 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 célula central permanecerá muerta, porque está rodeada por exactamente cinco células vivas.

  • Después de completar cada fila, los números en la matriz se actualizan dividiendo los números existentes por 7, descartando la parte decimal y agregando 49 veces los valores de las celdas en la nueva columna. Almacenar las tres columnas cada vez sería mucho más lento y menos elegante, tomaría al menos 20 bytes más y usaría tres listas en lugar de una, porque los valores de las celdas en cada fila deben almacenarse antes de actualizar las celdas. Esta es, con mucho, la forma más pequeña de almacenar posiciones de celda.

  • El fragmento int(3fPart(3cosh(da 1cuando la entrada es igual a 3/6, 2cuando es igual a 4/6 y 0cuando es igual a 0, 1/6, 2/6 o 5/6. Ahorra unos 6 bytes.

lirtosiast
fuente
19

Mathematica - 333

caracteristicas:

  • Interfaz interactiva: haga clic en las celdas para crear sus patrones

  • Buena cuadrícula

  • Botones: EJECUTAR, PAUSAR, BORRAR

El código está abajo.

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

ingrese la descripción de la imagen aquí

Si desea tener una idea de cómo funciona esto, el segundo ejemplo en este blog es solo una versión más elaborada (análisis de Fourier en vivo, mejor interfaz) del código anterior. El ejemplo debería ejecutarse directamente en su navegador después de la descarga gratuita del complemento.

Vitaliy Kaurov
fuente
2
+1, agradable para intentarlo. Sí, ese es el problema con este sitio, hay toneladas de viejas preguntas que uno tiende a pasar por alto.
Griffin
@Griffin gracias por notarlo en absoluto;)
Vitaliy Kaurov
15

C 1063 caracteres

Como desafío, hice esto en C usando la API de Windows poco amigable para el golf para IO en tiempo real. Si el bloqueo de mayúsculas está activado, la simulación se ejecutará. Se quedará quieto si el bloqueo de mayúsculas está desactivado. Dibuja patrones con el mouse; el clic izquierdo revive las celdas y el clic derecho mata las celdas.

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

El EXE compilado se puede encontrar aquí.

Editar: he comentado la fuente. Está disponible aquí

Kaslai
fuente
¡Me encantaría ver una versión comentada de esto!
luser droog
1
Claro, si puedo recordar lo que estaba pensando ... = p
Kaslai
1
@luserdroog Aquí está pastebin.com/BrX6wgUj
Kaslai
Esto es simplemente asombroso.
rayryeng - Restablece a Mónica el
12

J (39 caracteres)

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

Basado en esta versión APL (mismo algoritmo, convolución toroidal).

Ejemplo de uso:

   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
kaoD
fuente
10

Mathematica, 123 caracteres

Una implementación muy rudimentaria que no utiliza la función CellularAutomaton incorporada de Mathematica.

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

Ruby 1.9 + SDL (380 325 314)

EDITAR : 314 caracteres, y se corrigió un error con celdas adicionales que aparecían vivas en la primera iteración. Se aumentó el tamaño de la cuadrícula a 56 ya que la rutina de color solo mira los 8 bits más bajos.

EDITAR : Golfed hasta 325 caracteres. El ancho / alto de la cuadrícula ahora es 28, ya que 28 * 9 es el más grande que puede tener mientras usa el valor como color de fondo. También procesa solo un evento SDL por iteración ahora, lo que obvia el bucle interno por completo. Bastante apretado, creo!

La simulación comienza en pausa, con todas las células muertas. Puede presionar cualquier tecla para alternar entre pausa / pausa y hacer clic en cualquier celda para alternar entre vivo y muerto. Ejecuta una iteración cada décima de segundo.

El envoltorio es un poco torpe.

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}

Se ve como esto:

Captura de pantalla de la aplicación en acción.

Desafío divertido! Agradezco cualquier mejora que cualquiera pueda ver.

Paul Prestidge
fuente
Buen intento, pero puedo ver de inmediato que te has equivocado. No puedes tener un patrón como ese en GoL. Lea otra vez las reglas: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
Griffin
@Griffin Creo que la captura de pantalla se tomó después de pausar y alternar algunas celdas manualmente; sin embargo, volveré a verificar las reglas. ¡Gracias!
Paul Prestidge
77
@Griffin no puede el patrón de semilla estar en alguna configuración posible?
nuevo el
7

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

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

Sin golf:

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 mayor parte del código aquí es cosas de Swing GUI. El juego en sí está en el actionPerformedmétodo que se activa por Timer, y la función auxiliar nque cuenta vecinos.

Uso:

Compílelo scalac filenamey luego ejecútelo scala L.
Al hacer clic en un cuadrado, se cambia de vivo a muerto, y la opción de menú comienza y detiene el juego. Si desea cambiar el tamaño de la cuadrícula, cambie los primeros tres valores en la línea: var(w,h,c,d,r)=(20,20,20,0,false)son ancho, alto y tamaño de celda (en píxeles) respectivamente.

Gareth
fuente
Encontré 2 mejoras de golf: import java.awt.event._y contents+=m("Go",true)+=m("Stop",false)}}, lo que lleva a 1093 caracteres.
Usuario desconocido el
@usuario desconocido Gracias. Encontré algunas mejoras, hasta 1063 ahora.
Gareth
Maldición, has estado ocupado. ¡Seguid así! Probaré las respuestas cuando algunas personas más las publiquen.
Griffin
7

Pure Bash, 244 bytes

Funciona en un universo de 36x24 envuelto en toroidales:

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"

Como se trata de un script de shell, el método de entrada es congruente con otros comandos de shell, es decir, desde stdin:

$ ./conway.sh << EOF

   O 
    O 
  OOO 

EOF


  O O                                                       
   OO                                                       
   O                                                        

















    O                                                       
  O O                                                       
   OO                                                       

... etc.

Podemos redirigir la entrada desde cualquier fuente de texto, canalizada a través de un trfiltro para obtener generaciones iniciales interesantes, por ejemplo

man tr | tr [:alnum:] O | ./conway.sh
Trauma digital
fuente
6

JavaScript, 130

No respondimos totalmente al desafío, pero para el registro, aquí hay un motor de Juego de la Vida en 130 bytes hecho por Subzey y yo 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}
xem
fuente
Esto parece tener algunos problemas con la primera fila. Por ejemplo, configuración @@\n@@(2 por 2 cuadrados en la esquina superior izquierda) o .@\n.@\n.@. (Columna 1 por 3)
Annan
5

C # - 675 caracteres

Siempre quise escribir una versión de este programa. Nunca supe que solo tomaría una media hora perezosa para una versión rápida y sucia. (Jugar al golf lleva mucho más tiempo, por supuesto).

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

  • Ingrese un patrón de inicio haciendo clic en las celdas para activarlas (activas).
  • Comienza el juego presionando cualquier tecla del teclado.
  • El juego se ejecuta durante 99 generaciones cada vez que se presiona una tecla (podría haber hecho 9 para guardar un personaje, pero eso parecía demasiado flojo).

Compromisos de golf

  • Solo puede encender las celdas con el mouse, no apagarlas, por lo que si comete un error, debe reiniciar el programa.
  • No hay líneas de cuadrícula, pero eso no daña demasiado la jugabilidad.
  • La velocidad de actualización es proporcional a la velocidad de la CPU, por lo que en computadoras muy rápidas probablemente sea solo un desenfoque.
  • Las células vivas son rojas porque "negro" usa 2 caracteres más.
  • La pequeñez de las celdas y el hecho de que no consuman todo el espacio del formulario también son compromisos para salvar caracteres.
Igby Largeman
fuente
5

GW-BASIC, 1086 1035 bytes (tokenizado)

En forma de token, esto es 1035 bytes. (El formulario ASCII es, por supuesto, un poco más largo). Se obtiene el formulario con token utilizando el SAVE"lifecomando sin agregarlo ",aen el intérprete.

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

Esta es la versión de golf máximo, pero aún tiene características: al comenzar, obtienes un editor, en el que puedes moverte con las teclas del cursor; el espacio activa / desactiva las bacterias en el campo actual, cborra la pantalla, el modo Regreso inicia el juego

Aquí sigue una versión menos ofuscada, que también establece un tablero de juego inicial con dos estructuras (una cosa giratoria y un planeador):

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

Escribí esto en 15 minutos mientras estaba aburrido y esperando a un amigo, que estaba jugando al golf con su "aprendiz" para el Juego de la Vida de Conway al mismo tiempo.

Funciona de esta manera: inmediatamente usa el búfer de pantalla de modo de texto 80x25 (cambie la inicial DEF SEGpara usar &hB000si está en una tarjeta gráfica Hercules; esta configuración funciona con Qemu y dosbox (más lento)). Un asterisco *es una bacteria.

Funciona en dos pasos: primero, los lugares de nacimiento están marcados con +y la muerte marca sus objetivos con .. En el segundo pase, +y .son reemplazados por *y , respectivamente.

Lo TIMERimportante es hacer que espere medio segundo después de cada ronda, en caso de que su host Qemu sea muy rápido ☺

No espero un precio de victorias más cortas aquí, sino uno genial, especialmente teniendo en cuenta la configuración inicial del tablero. También tengo una versión donde el motor del juego fue reemplazado por código de ensamblaje, en caso de que estés interesado ...

mirabilos
fuente
Teniendo en cuenta que incrementó sus etiquetas en 1 en la versión sin golf, ¿es posible hacer lo mismo en la versión con golf? (es decir, 1, 2, 3, etc.) ¿O es que los números de línea no cuentan?
Zacharý
los números de línea, cuando se tokenizan, cuentan como palabra (16 bits), si no estoy totalmente equivocado
mirabilos
Está bien, entonces, supongo que debo haber estado pensando en otro dialecto BÁSICO entonces
Zacharý
@ Zacharý Haga clic en "Formato de programa tokenizado GW-BASIC" y luego en "Formato de programa" aquí para ver que, de hecho, los números de línea son constantemente dos bytes y para obtener detalles más detallados sobre el formato de token.
mirabilos
5

Mathematica, 115 bytes

Aquí hay una solución fácil para esto:

ListAnimate[ArrayPlot/@CellularAutomaton[{224,{2,{{2,2,2},{2,1,2},
{2,2,2}}},{1,1}},{RandomInteger[1,{9,9}],0},90]]
JeremyKun
fuente
1
Mathematica está bien, pero como lo establecen las reglas, el programa debe permitir al usuario ingresar sus propios patrones. Esta regla es intencional ya que algunos idiomas permiten implementaciones cortas como esta, pero sin interacción del usuario. Claro que puedes poner tu propia matriz allí, pero no va a ganar.
Griffin
La "entrada" en Mathematica es principalmente a través de la interfaz del cuaderno, por lo que no creo que la "interacción del usuario" sea realmente posible. Simplemente reemplace el argumento RandomInteger para la función CellularAutomaton con lo que desee y vuelva a evaluar el código.
JeremyKun
3
La interacción del usuario es posible. El método más simple que se me ocurre en este momento es una variedad de botones. Pruébalo, hombre.
Griffin
4

Java (OpenJDK 8) - 400 388 367 bytes

Segunda y (probablemente) edición final: se las arregló para jugar al golf 21 bytes adicionales después de encontrar estas minas de oro (imo) : definitivamente recomiendo que nuevas personas las lean (especialmente si vas a probar algunos de estos desafíos usando Java).

Código resultante (probablemente termine jugando al golf aún más si descubro cómo acortar esos bucles doblemente anidados ...):

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

Pruébalo en línea!

(La publicación original comienza aquí).

De hecho, pensé por un momento que al menos podría desafiar la mejor respuesta de Python con mi (posiblemente limitado) conocimiento de Java lol ... Fue un desafío en el que, sin embargo, disfruté participar (a pesar de haberme unido a la fiesta, tal vez solo un un poco tarde...)

Realmente no hay mucho: explicación básica de la siguiente manera (sin 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

(Más información sobre las declaraciones lambda en Java 8 aquí )

Sí, hay un problema con mi enfoque.

Como la mayoría de ustedes probablemente notaron, mi código de golf tal como está actualmente se repetirá para siempre. Para evitar esto, se puede introducir un contador en la parte superior y usarlo en el ciclo while para mostrar solo n(en este caso, 5) iteraciones de la siguiente manera (observe la nueva bvariable agregada):

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

Además, algunos puntos que vale la pena mencionar. Este programa no verifica si la entrada es correcta y, por lo tanto, fallará con (lo más probable) un ArrayOutOfBoundsException; como tal, asegúrese de verificar que la entrada sea válida completando completamente una parte de una matriz (las matrices ensartadas arrojarán la excepción mencionada anteriormente). Además, la placa como se ve actualmente es 'fluida', es decir, no hay separación entre una generación y la siguiente. Si desea agregar eso para verificar que las generaciones que se están produciendo sean válidas, se System.out.println();debe agregar un extra justo antes for(int[]t:u)Arrays.fill(t,0);(vea esto ¡ Pruébelo en línea! Para mayor claridad). Y por último, pero no menos importante, dado que este es mi primer código de golf, cualquier comentario es muy apreciado :)

Código anterior de la respuesta anterior de 388 bytes:

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

Y a partir de la respuesta inicial de 400 bytes:

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);}
NotBaal
fuente
Increíble primer post, bienvenido a PPCG!
Zacharý
Gracias, definitivamente voy a hacer más de estos, son divertidos :)
NotBaal
Únete a nosotros, tenemos a Dennis. Además, este no es un programa completo ni una función, que debe ser, IIRC.
Zacharý
Ah, claro, olvidé la parte del "programa": P Editar eso en un momento.
NotBaal
También puede ser una función también.
Zacharý
4

Stencil , 6 bytes

No es mi idioma favorito, pero es corto ...

4 bytes de código más las banderas nlist y Torus.

3me

Pruébalo en línea!

Es ...
3 3
 un miembro de
m la m Oore-barrio-recuento con uno mismo o
e el páramo e -neighbourhood-recuento sin auto
...?

Adán
fuente
3

Scala - 799 caracteres

Ejecutar como un script Un clic del mouse en un cuadrado lo activa o desactiva y cualquier tecla inicia o detiene la generación.

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)
DonMac
fuente
3

J, 45

Pensé darle una oportunidad a J. Todavía no está particularmente bien golfizado, pero lo intentaré pronto.

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

Ejemplo:

   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
Copiar
fuente
3

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

Creo que esto satisface todos los requisitos.

Sin golf:

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

No tengo Matlab instalado en este momento para probarlo, acabo de jugar el código que escribí hace unos años.
Sin golf:

%% 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á codificado pero puede ser cualquier cosa
  • envuelve alrededor
  • para la entrada del usuario, uno puede cambiar la placa inicial ya sea codificando otra matriz o usando el editor de variables. No es bonita, pero funciona
  • Se pueden guardar 20 caracteres si se omite la salida gráfica, el tablero todavía se imprimirá como texto en cada iteración. Las celdas de un píxel que cambian cada milisegundo no son muy útiles de todos modos
DenDenDo
fuente
funciona en R2014a, recién probado
masterX244
3

Perl, 218 216 211 202 bytes

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

(No hay nueva línea al final de este código).

Lee el patrón inicial a partir de la entrada estándar, como un archivo de texto donde las celdas vivas se representan como 1, las celdas muertas se representan como un espacio, las líneas están separadas por una nueva línea. La entrada no tendrá caracteres distintos a estos. Las líneas pueden ser de longitud variable, y se rellenarán o truncarán exactamente a 79 de ancho. La entrada de ejemplo es una pistola planeadora:

                                  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

A medida que el programa ejecuta Game of Life, cada estado se descarga a la salida estándar en un formato similar a la entrada, luego se retrasa 0.1 segundos. El retraso se puede personalizar cambiando el cuarto argumento de la llamada de selección.

El tablero de juego está codificado en tamaño 79x23. Está envuelto en un toro: si dejas el tablero en la parte inferior, terminas en la parte superior; si te vas del lado derecho, terminas en el lado izquierdo pero desplazas una fila hacia abajo.

Aquí hay una versión alternativa que no lee ninguna entrada y comienza desde una placa aleatoria:

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

Este código se deriva de un programa de perl ofuscado de juego de vida que escribí hace años . Lo he cambiado mucho para que el tablero sea toroidal y el código sea el golf.

Probablemente este no sea el método más corto para implementar Game of Life en Perl, pero es uno de los menos comprensibles.

El tablero se almacena $bcomo una cadena de '1'y ' ', uno para cada celda, solo todo se repite al menos tres veces. La tercera llamada de desempaquetar extrae 17 valores para cada celda: hay uno para la celda en sí y dos para cada una de las ocho celdas vecinas, en un orden arbitrario, y cada valor es '1'o una cadena vacía. La celda debe estar activa en la próxima iteración si el número de '1'valores entre estos 17 valores es 5, 6 o 7. La tercera llamada del paquete concatena estos 17 valores en un campo de 18 caracteres de ancho alineado a la izquierda y rellenado con nul bytes a la derecha . La segunda llamada de desempaquetar toma un campo tan ancho de 18, se despacha en el personaje en la posición 7, desempaqueta el espacio de la posición 17 si es un'1', o desempaqueta el personaje de la posición 4 de lo contrario. Este resultado es exactamente el valor que la celda debería tener en la próxima generación.

b_jonas
fuente
2

Python, 589 bytes

Botones del mouse: izquierda - poner una celda, derecha - eliminar una celda, centro - iniciar / detener.

de Tkinter import *
copia de importación
z = rango
F = 50
T = Tk ()
S = 9
f = [F * [0] para i en '7' * F]
c = Lienzo (T, ancho = S * F, altura = 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) si un otro c borra (f [y] [x])
r = 1
def R (e): global r; r = 1-r
exec ("c.bind ('<Botón-% i>', lambda e: p (ex / S, ey / S,% i));" * 2% (1,1,3,0))
c.bind ('<Button-2>', R)
def L ():
 T.después (99, L)
 si r: volver
 g = copy.deepcopy (f)
 para y en z (F):
	para x en z (F):
	 n = 8
	 para j en z (-1,2):
		para i en z (-1,2):
		 si i o j: n- = no g [(y + j)% F] [(x + i)% F]
	 si 1 <n <4:
		si n == 3 y no g [y] [x]: p (x, y, 1)
	 más: p (x, y, 0)
L ()
T.mainloop ()

Y aquí hay una versión donde puedes arrastrar el mouse para dibujar. Los gráficos son un poco más agradables.

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()
Oleh Prypin
fuente
Esto no sigue las reglas del juego de la vida correctamente.
Steven Rumbalski el
1
@StevenRumbalski: ¿En serio?
Oleh Prypin
2
De Verdad. Tiene un error de sangría en su segunda versión. La sección que comienza if 1<n<4:debe tener sangría al mismo nivel quefor j in z(-1,2):
Steven Rumbalski
2

Python 2, 456 bytes

Si bien sé que esta es una publicación antigua, no pude evitar darle una oportunidad. El tablero inicial puede ser de cualquier tamaño siempre que dibuje un borde alrededor y tenga un espacio adicional en la última línea.

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 (tenga en cuenta el espacio extra en la última línea)

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

Como correr

python Golf.py < input.txt
Raffi
fuente
time.sleep(0.1)==None=> not time.sleep(.1), (f=='@'and(x==3 or x==2)) o (f == '' yx == 3) =>x==3or f=='@'and x==2
CalculatorFeline
^, Olvidó uno, 1 if=> 1if.
Zacharý
2

Tratamiento 270,261 249 bytes

La cuadrícula son los 100 * 100 píxeles de pantalla, la entrada viene en forma de imagen 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();}

Sin golf

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

captura de pantalla

PrincePolka
fuente
2

Lua + LÖVE / Love2D , 653 bytes

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

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

Haga clic en el campo para agregar células vivas. Haga clic fuera del campo para ejecutarlo.

Pruébalo en línea!

ingrese la descripción de la imagen aquí

Sheepolution
fuente
1

Posdata 529 515

Comenzó con el ejemplo de Rosetta Code . Invoque con un argumento de nombre de archivo ( gs -- gol.ps pulsar), el archivo que contiene 20 * 20 números binarios (separados por espacio). Bucle infinito: tablero de dibujo, espere a entrar, calcule la próxima generación.

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

Espaciado, con algunos comentarios de pila (solo los que necesitaba).

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

archivo de datos de 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
luser droog
fuente
1

JavaScript 676

Lo siento, Griffin, simplemente no pude ver tu código y no volver a escribirlo ligeramente ... ¡tuve que quitar dos caracteres, pero valió 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}

Pero como dicen, es más fácil pedir perdón que permiso ...;)

WallyWest
fuente
1

Octava (153)

lo mismo que Matlab de DenDenDo en Shortest Game of Life , pero tuvo que cambiar imshow a 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
Martin Novy
fuente
1

Python 2: 334 bytes

Solo 6 años de retraso.

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"

Puedes ejecutarlo como:

python gol.py
0000000
0001000
0000100
0011100
0000000
0000000
0000000

Donde los 0 y 1 representan células muertas y vivas, una nueva línea adicional al final comienza la ejecución.

Las cuadrículas deben ser cuadradas.

Es más fácil de ejecutar que el Python más corto, admite cuadrículas de cualquier tamaño y se ve bonito cuando se ejecuta.

También es 100 bytes más, así que está eso.

Backerupper
fuente
0

PHP, 201 bytes (no probado)

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;

Corre con -nr.

Descompostura

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