Jogo mais curto da vida


59

O Jogo da Vida de Conway é o exemplo clássico de automação celular. As células formam uma grade quadrada e cada uma tem dois estados: vivos ou mortos. Em cada turno, cada célula é atualizada simultaneamente de acordo com seu estado e o de seus oito vizinhos:

  • Uma célula viva permanece viva se tiver exatamente dois ou três vizinhos vivos
  • Uma célula morta ganha vida se tiver exatamente três vizinhos vivos

Sua missão, se você optar por aceitá-la, é codificar a implementação mais curta do Game of Life no seu idioma favorito.

As regras:

  • A grade deve ter pelo menos 20x20
  • A grade deve envolver (para que a grade seja como a superfície de um Torus)
  • Sua implementação deve permitir que o usuário insira seus próprios padrões iniciais
  • GoL é um pouco inútil se você não pode ver o que está acontecendo, portanto deve haver saída visual do autômato em execução, com o resultado de cada turno sendo mostrado por tempo suficiente para ser visto!

8
Anteriormente, no Stack Overflow: Code Golf: Game of Life , de Conway , e não deixe de conferir o link de implementação da APL nos comentários.
dmckee

11
Ah, eu não vi isso. Mas isso é um pouco diferente (salva-me apagar o trabalho de colocar o desafio juntos?
Griffin

6
Isso não é um problema. Muitos quebra-cabeças já executados no Stack Overflow também foram feitos aqui, mas as pessoas dirão que eu sou obsessivo em vincular-me a desafios semelhantes.
precisa saber é

@ Griffin: Você pode remover todos esses ;antes de }s. Também vars podem ser eliminados às vezes (se não quebrar seu código). E para uma linha fors, ifs etc, você pode eliminar o { }completamente: for(...) for(...) dosomething().
Pimvdb

@ pimvdb, saúde, ainda não joguei totalmente, ainda não tive tempo. só queria mostrar que eu também tentava, em vez de colocar um desafio à toa. Golf-lo ao máximo em breve.
Griffin

Respostas:


27

Canvas HTML5 com JavaScript, 940 639 586 519 personagens

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

Eu sempre quis fazer algo com canvas, então aqui está minha tentativa (versão original online ). Você pode alternar as células clicando em (também possível no modo de execução).

Agora você também pode experimentar a nova versão aqui .

Infelizmente, existe um problema que ainda não consegui solucionar. A versão online tem 11 caracteres a mais porque o jsFiddle coloca um nó de texto imediatamente antes da tela (por quê?) E, portanto, a tela não é mais o primeiro filho.

Edit 1: Muitas otimizações e reestruturações.

Edit 2: Várias mudanças menores.

Edit 3: Inline o bloco de script completo mais pequenas alterações.


Bom, mas mude o atraso do intervalo para 1torná-lo tão rápido quanto o meu, em vez de pisar devagar. Além disso, se você deseja implementar o desenho (em vez de clicar em cada quadrado), pode arredondar a posição do mouse para o tamanho de bloco mais próximo e preencher o retângulo nesse ponto. Mais personagens, mas mais pontos.
Griffin

Você pode substituir new Array('#FFF','#800')por ['#FFF','#800'].
Lowjacker 15/08/11

Apesar de dizer isso sobre o desenho, meu super-jogador de golfe não permite o desenho e é feio como o pecado. Haha Você pode definir suas duas cores na smatriz como tane, reduma vez que são as duas cores com as representações mais curtas - economiza dois caracteres. Além disso, se possível, coloque a versão literal de jno intervalo. Tenho certeza de que há muito mais para se espremer também.
Griffin

@ Griffin e Lowjacker: muito obrigado. Também tenho certeza de que você pode jogar muito mais golfe (e já tem algumas idéias). Infelizmente, não encontrei tempo para fazê-lo. A versão melhor golfed seguirá amanhã - Espero ...
Howard

2
Você pode remover as tags html e body. Ele vai funcionar o mesmo
arodebaugh

32

Python, 219 caracteres

Eu fui para o golfe máximo, com interface apenas o suficiente para satisfazer a pergunta.

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)

Você executa assim:

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

Os números na lista representam as coordenadas das células iniciais. A primeira linha é 0-19, a segunda linha é 20-39, etc.

Execute-o em um terminal com 21 linhas e parece bem legal.


11
Isso totalmente deveria ter vencido. Eu acho que 'facilidade de entrada' foi ponderada razoavelmente alta.
Primo

@primo Eu chegaria a sugerir que o mma deveria ter uma competição separada.
Luser droog

2
Então é essa Vida de Py então?
Christopher Wirt

Você sempre pode salvar mais um caractere ... 2-(p in P)== 2-({p}<P). Mas então você teria que mudar sua entrada para {8,29,47,48,49}:)
JBernardo

21

TI-BASIC, 96 bytes (87 para entradas não concorrentes)

Para a sua calculadora gráfica da série TI-84 (!). Este foi um grande desafio, porque não há nenhuma maneira fácil de escrever uma gráfica rotina tamponada (definitivamente nada embutido), ea tela do gráfico tem comandos apenas quatro gráficos relevantes: Pxl-On(), Pxl-Off(), Pxl-Change(), e pxl-Test().

Usa todos os pixels acessíveis na tela e envolve corretamente. Cada célula é um pixel e o programa atualiza linha por linha horizontalmente à direita na tela. Como as calculadoras possuem apenas um processador z80 de 15MHz e o BASIC é uma linguagem de interpretação lenta, o código obtém apenas um quadro a cada cinco minutos.

A entrada do usuário é fácil: antes de executar o programa, use a ferramenta Caneta para desenhar sua forma na tela do gráfico.

Adaptado da minha inscrição para um concurso de código de golfe no fórum da 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

Versão Omnimaga (87 bytes)

Esse código possui um recurso adicional: detecta se está sendo executado pela primeira vez e se randomiza o estado da tela. Nas execuções subsequentes, a simulação continua automaticamente se for interrompida após o término de um quadro. No entanto, não é uma entrada concorrente porque não quebra a tela; as células na borda externa sempre serão consideradas mortas se a tela do gráfico for limpa anteriormente.

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 versão é provavelmente o código mais elaborado que já escrevi e contém algumas otimizações ofuscantes realmente desagradáveis:

  • Eu uso o estado do relógio como uma bandeira. No início do programa, o relógio de data / hora está ativado e eu uso o valor do sinalizador global isClockOn para determinar se é a primeira iteração. Depois que o primeiro quadro é desenhado, desligo o relógio. Economiza um byte sobre o outro método mais curto e cerca de quatro sobre o método óbvio.

  • Eu armazeno os estados das três colunas ao lado da que está sendo atualizada em uma matriz de 63 elementos com base 7. O local dos 49 mantém a coluna à direita, o local dos 7 mantém a coluna do meio e o local das unidades mantém a coluna da esquerda - 1 para uma célula viva e 0 para uma célula morta. Então eu pego o mod 6 restante da soma dos três números ao redor da célula que está sendo modificada para encontrar o número total de células vizinhas vivas (é como a divisibilidade por 9 truques - na base 7, o mod 6 restante é igual à soma de os dígitos). Economiza cerca de 10 bytes por si só e oferece a oportunidade de usar as próximas duas otimizações. Diagrama de exemplo (digamos que exista um planador centralizado em uma determinada coluna em 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
    ...
    

    A célula central permanecerá morta, porque está cercada por exatamente cinco células vivas.

  • Após a conclusão de cada linha, os números na matriz são atualizados dividindo os números existentes por 7, descartando a parte decimal e adicionando 49 vezes os valores das células na nova coluna. Armazenar todas as três colunas de cada vez seria muito mais lento e menos elegante, consumir pelo menos mais 20 bytes e usar três listas em vez de uma, porque os valores das células em cada linha devem ser armazenados antes que as células sejam atualizadas. Essa é de longe a menor maneira de armazenar as posições das células.

  • O trecho int(3fPart(3cosh(fornece 1quando a entrada é igual a 3/6, 2quando é igual a 4/6 e 0quando é igual a 0, 1/6, 2/6 ou 5/6. Economiza cerca de 6 bytes.


19

Mathematica - 333

Recursos:

  • Interface interativa: clique nas células para criar seus padrões

  • Grade agradável

  • Botões: EXECUTAR, PAUSAR, LIMPAR

O código está abaixo.

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

insira a descrição da imagem aqui

Se você quiser entender como isso funciona, o segundo exemplo deste blog é apenas uma versão mais elaborada (análise ao vivo de Fourier, melhor interface) do código acima. O exemplo deve ser executado diretamente no seu navegador após o download gratuito do plugin.


2
+1, bom para experimentar. Sim, esse é o problema deste site. Há toneladas de perguntas antigas das quais tende a se perder.
Griffin

@Griffin obrigado por perceber em tudo;)
Vitaliy Kaurov

15

Caracteres C 1063

Como desafio, fiz isso em C usando a API do Windows, hostil ao golfe, para E / S em tempo real. Se o capslock estiver ativado, a simulação será executada. Ele ficará parado se o capslock estiver desativado. Desenhe padrões com o mouse; clique esquerdo revive células e clique direito mata células.

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

O EXE compilado pode ser encontrado aqui

Edit: eu comentei a fonte. Está disponível aqui


Eu adoraria ver uma versão comentada disso!
Luser droog

11
Claro, se me lembro que eu estava pensando ... = p
Kaslai

11
@luserdroog Aqui está pastebin.com/BrX6wgUj
Kaslai 22/12/12

Isso é simplesmente incrível.
rayryeng - Reinstala Monica

12

J (39 caracteres)

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

Baseado nesta versão do APL (mesmo algoritmo, convolução toroidal).

Exemplo 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

10

Mathematica, 123 caracteres

Uma implementação muito rudimentar que não usa a função CellularAutomaton interna do 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 caracteres e corrigido um erro com células extras aparecendo ativas na primeira iteração. Aumentou o tamanho da grade para 56, uma vez que a rotina de cores analisa apenas os 8 bits mais baixos.

Edição : Golfed até 325 caracteres. A largura / altura da grade agora é 28, pois 28 * 9 é a maior que você pode ter enquanto ainda usa o valor como cor de fundo. Ele também processa apenas um evento SDL por iteração agora, o que evita completamente o loop interno. Bem apertado, eu acho!

A simulação começa em pausa, com todas as células mortas. Você pode pressionar qualquer tecla para alternar entre pausar / não pausar e clicar em qualquer célula para alternar entre viva e morta. Executa uma iteração a cada décimo de segundo.

A embalagem é um pouco instável.

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 parece com isso:

Captura de tela do aplicativo em ação

Desafio divertido! Congratulo-me com quaisquer melhorias que alguém possa ver.


Boa tentativa, mas posso ver imediatamente que você deu errado. Você não pode ter um padrão como esse no GoL. Leia outra vez as regras: en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
Griffin

@ Griffin Acho que a captura de tela foi feita após pausar e alternar algumas células manualmente - vou verificar as regras novamente. Obrigado!
Paul Prestidge

7
@ Griffin não pode o padrão de semente estar em qualquer configuração possível?
Ardnew 8/08

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

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

A maior parte do código aqui é material da GUI do Swing. O jogo em si está no actionPerformedmétodo que é acionado pelo Timer, e a função auxiliar nque conta os vizinhos.

Uso:

Compile-o scalac filenamee execute-o com scala L.
Clicar em um quadrado vira-o de vivo para morto, e a opção de menu inicia e para o jogo. Se você deseja alterar o tamanho da grade, altere os três primeiros valores da linha: var(w,h,c,d,r)=(20,20,20,0,false)eles são largura, altura e tamanho da célula (em pixels), respectivamente.


Eu encontrei duas melhorias no golfe: import java.awt.event._e contents+=m("Go",true)+=m("Stop",false)}}, levando a 1093 caracteres.
usuário desconhecido

@ usuário desconhecido Obrigado. Eu mesmo encontrei algumas melhorias - até 1063 agora.
Gareth

Porra, você esteve ocupado. Mantem! Testarei as respostas quando mais algumas pessoas as postarem.
Griffin

7

Pure Bash, 244 bytes

Funciona em um universo 36x24 envolto em toroidal:

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 este é um script shell, o método de entrada é congruente com outros comandos shell - ou seja, do stdin:

$ ./conway.sh << EOF

   O 
    O 
  OOO 

EOF


  O O                                                       
   OO                                                       
   O                                                        

















    O                                                       
  O O                                                       
   OO                                                       

... etc

Podemos redirecionar a entrada de qualquer fonte de texto, canalizada através de um trfiltro para obter gerações iniciais interessantes, por exemplo

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

6

JavaScript, 130

Não respondendo totalmente ao desafio, mas, para constar, aqui está um mecanismo do Game of Life em 130 bytes, criado por Subzey e eu em 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}

Isso parece ter alguns problemas com a primeira linha. Por exemplo, configuração @@\n@@(quadrado 2 por 2 no canto superior esquerdo) ou .@\n.@\n.@. (Coluna 1 por 3)
Annan

5

C # - 675 caracteres

Eu sempre quis escrever uma versão deste programa. Nunca soube que levaria apenas meia hora preguiçosa para uma versão rápida e suja. (O golfe leva muito mais tempo, é claro.)

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

  • Digite um padrão inicial clicando nas células para ativá-las (ativas).
  • Inicie o jogo pressionando qualquer tecla do teclado.
  • O jogo dura 99 gerações sempre que uma tecla é pressionada (eu poderia ter conseguido 9 para salvar um caractere, mas isso parecia muito ruim).

Compromissos de golfe

  • Você só pode ativar as células com o mouse, e não desativá-las; portanto, se você cometer um erro, precisará reiniciar o programa.
  • Não há linhas de grade, mas isso não prejudica muito a jogabilidade.
  • A velocidade de atualização é proporcional à velocidade da CPU; portanto, em computadores muito rápidos, provavelmente será apenas um borrão.
  • As células vivas são vermelhas porque "preto" usa mais 2 caracteres.
  • A pequenez das células e o fato de elas não ocuparem todo o espaço do formulário também comprometem a economia de caracteres.

5

GW-BASIC, 1086 1035 bytes (tokenizado)

No formato tokenizado, são 1035 bytes. (O formulário ASCII é, é claro, um pouco mais longo.) Você obtém o formulário tokenizado usando o SAVE"lifecomando sem anexar ",ano 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 é a versão com o máximo de golfe, mas ainda com muitos recursos: ao iniciar, você recebe um editor, no qual pode se mover com as teclas do cursor; O espaço ativa / desativa as bactérias no campo atual, climpa a tela e Return inicia o modo de jogo.

A seguir, uma versão menos ofuscada, que também define um tabuleiro de jogo inicial com duas estruturas (uma coisa de rotação circular e um planador):

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

Escrevi isso em 15 minutos enquanto estava entediado e esperando por um amigo, que jogava golfe com seu “aprendiz” no jogo da vida de Conway, ao mesmo tempo.

Funciona assim: Usa imediatamente o buffer de tela de modo de texto de 80x25 (altere a inicial DEF SEGa ser usada &hB000se você estiver em uma placa gráfica Hercules; essas configurações funcionam com o Qemu e o dosbox (mais lento)). Um asterisco *é uma bactéria.

Ele funciona em duas passagens: primeiro, os locais de nascimento são marcados com +e a morte marca seus alvos .. Na segunda passagem, +e .são substituídos por *e , respectivamente.

O TIMERimportante é fazer com que espere meio segundo após cada rodada, caso o seu host Qemu seja muito rápido ☺

Eu não estou esperando por um preço de menor ganho aqui, mas por um preço bacana, especialmente considerando a configuração inicial do quadro. Eu também tenho uma versão em que o mecanismo do jogo foi substituído pelo código de montagem, caso você esteja interessado…


Considerando que você incrementou seus rótulos em 1 na versão sem golfe, é possível fazer o mesmo na versão com golfe? (ie, 1, 2, 3, etc.) Ou será que os números de linha não contam?
Zachary

números de linha, quando tokenised, contam como palavra (16 bits), se eu não estou totalmente equivocadas
mirabilos

Ok, acho que devo estar pensando em outro dialeto do BASIC.
`` Zacharý

@ Zacharý Clique em “GW-BASIC tokenised program format” e depois em “Program format” aqui para ver que, de fato, os números de linha são constantemente de dois bytes e para obter detalhes mais detalhados sobre o formato do token.
mirabilos

5

Mathematica, 115 bytes

Aqui está uma cópia fácil para isso:

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

11
O Mathematica é bom, mas como as regras indicam, o programa deve permitir que o usuário insira seus próprios padrões. Essa regra é intencional, pois alguns idiomas permitem implementações curtas como essa, mas sem interação do usuário. Claro que você pode colocar sua própria matriz lá, mas não vai ganhar.
Griffin

"entrada" no Mathematica é principalmente através da interface do notebook, então eu não acho que a "interação do usuário" seja realmente possível. Você acabou de substituir o argumento RandomInteger pela função CellularAutomaton pelo que desejar e reavaliar o código.
precisa saber é o seguinte

3
A interação do usuário é possível. O método mais simplista que consigo pensar agora é uma variedade de botões. Vá em frente, cara.
Griffin

4

Java (OpenJDK 8) - 400 388 367 bytes

Segunda e (provavelmente) Edição Final: Conseguiu jogar um extra de 21 bytes depois de encontrar essas (imo) minas de ouro - definitivamente recomendo que novas pessoas as leiam (especialmente se você tentar alguns desses desafios usando Java).

Código resultante (provavelmente acabará jogando golfe ainda mais se eu descobrir como reduzir os duplos aninhados para loops ...):

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

Experimente online!

(A postagem original começa aqui.)

Na verdade, pensei por um momento que eu seria capaz de, pelo menos, desafiar a melhor resposta em Python com meu conhecimento (possivelmente limitado) de Java lol ... Foi um desafio no qual eu gostei de participar (apesar de ter me juntado à festa talvez apenas um um pouco tarde ...)

Na verdade, não há muito - explicação básica da seguinte maneira (não destruída):

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

(mais informações sobre instruções lambda no Java 8 aqui )

Sim, há um problema com minha abordagem.

Como muitos de vocês já devem ter notado, meu código de golfe atual permanece em loop para sempre. Para evitar isso, um contador pode ser introduzido na parte superior e usado no loop while para exibir apenas n(neste caso, 5) iterações da seguinte maneira (observe a nova bvariável adicionada):

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

Além disso, alguns pontos que vale a pena mencionar. Este programa não verifica se a entrada está correta e, portanto, falhará com (provavelmente) an ArrayOutOfBoundsException; como tal, verifique se a entrada é válida preenchendo completamente uma parte de uma matriz (matrizes no espeto lançarão a exceção mencionada acima). Além disso, o quadro atual parece "fluido" - isto é, não há separação entre uma geração e a seguinte. Se você deseja adicionar isso para verificar se as gerações que estão sendo produzidas são realmente válidas, é System.out.println();necessário adicionar mais um pouco antes for(int[]t:u)Arrays.fill(t,0);(consulte a seção Experimente online! Para maior clareza). E por último, mas não menos importante, dado que este é o meu primeiro código de golfe, qualquer feedback é muito apreciado :)

Código antigo da resposta 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);}}

E a partir da resposta 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);}

Incrível primeiro post, bem-vindo ao PPCG!
Zacharý 14/08/19

Obrigado, eu definitivamente vou estar fazendo mais destes - eles são divertidos :)
NotBaal

Se juntar a nós, temos Dennis. Além disso, este não é um programa completo nem uma função, que precisa ser, IIRC.
Zacharý 14/08/19

Ah, certo, esqueci a parte do 'programa': P Editando isso daqui a pouco.
precisa saber é o seguinte

Também pode ser uma função também.
Zachary

4

Estêncil , 6 bytes

Não é meu idioma favorito, mas é curto…

4 bytes de código mais os sinalizadores nlist e Torus.

3me

Experimente online!

É ...
3 3
 um membro de
m a m oore-bairro-count com auto ou
e o pântano e -neighbourhood-count sem auto
...?


3

Scala - 799 caracteres

Execute como um script. Um clique do mouse em um quadrado o ativa ou desativa e qualquer tecla inicia ou interrompe a geração.

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

Eu pensei em dar uma chance a J. Ainda não está particularmente bem jogado, mas tentarei outra vez em breve.

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

Exemplo:

   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

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

Acredito que isso satisfaça todos os requisitos.

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

Não tenho o Matlab instalado agora para testá-lo, apenas joguei o código que escrevi alguns anos atrás.
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
  • O tamanho da placa é codificado, mas pode ser qualquer coisa
  • envolve
  • para entrada do usuário, pode-se alterar o painel inicial codificando outra matriz ou usando o editor de variáveis. Não é bonito, mas funciona
  • Podem ser salvos 20 caracteres se a saída gráfica for ignorada, o quadro ainda será impresso como texto a cada iteração. As células de um pixel que mudam a cada milissegundo não são muito úteis de qualquer maneira

funciona no R2014a, apenas testado
masterX244 6/14

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}

(Nenhuma nova linha no final deste código.)

Lê o padrão inicial da entrada padrão, como um arquivo de texto em que as células vivas são representadas como 1, as células mortas são representadas como um espaço, as linhas são separadas por uma nova linha. A entrada não deve ter caracteres diferentes desses. As linhas podem ter comprimento variável e serão preenchidas ou truncadas com exatamente 79 de largura. Exemplo de entrada é uma pistola de asa delta:

                                  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

À medida que o programa executa o Game of Life, todos os estados são transferidos para a saída padrão em um formato semelhante à entrada e atrasam 0,1 segundos. O atraso pode ser personalizado alterando o quarto argumento da chamada de seleção.

O tabuleiro do jogo é codificado no tamanho 79x23. Está envolto em um toro: se você deixar a prancha no fundo, acaba no topo; se você sair do lado direito, acaba no lado esquerdo, mas mudou uma linha para baixo.

Aqui está uma versão alternativa que não lê nenhuma entrada e começa em um quadro aleatório:

$,=$/;$/=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 é derivado de um programa ofuscado da vida perl que escrevi anos atrás . Eu mudei muito para tornar o tabuleiro toroidal e o código do golfe.

Este provavelmente não é o método mais curto para implementar o Game of Life em perl, mas é um dos menos compreensíveis.

O quadro é armazenado $bcomo uma sequência de '1'e ' ', uma para cada célula, apenas a coisa toda é repetida pelo menos três vezes. A terceira chamada de descompactação extrai 17 valores para cada célula: há um para a própria célula e dois para cada uma das oito células vizinhas, em uma ordem arbitrária, e cada valor é '1'ou uma sequência vazia. A célula deve estar ativa na próxima iteração se o número de '1'valores entre esses 17 valores for 5, 6 ou 7. A chamada do terceiro pacote concatena esses 17 valores para um campo amplo de 18 caracteres à esquerda alinhado e preenchido com nul bytes à direita . A segunda chamada de desempacotamento ocupa um campo tão amplo de 18, despacha o personagem na posição 7, descompacta o espaço da posição 17, se for um'1'ou descompacta o personagem da posição 4, caso contrário. Esse resultado é exatamente o valor que a célula deve ter na próxima geração.


2

Python, 589 bytes

Botões do mouse: esquerda - coloque uma célula, direita - remova uma célula, meio - inicie / pare.

da importação Tkinter *
cópia de importação
z = intervalo
F = 50
T = Tk ()
S = 9
f = [F * [0] para i in'7 '* F]
c = Tela (T, largura = S * F, altura = S * F)
c.pack ()
def p (x, y, a): f [y] [x] = f [y] [x] ou c.criar_oval (x * S, y * S, x * S + S, y * S + S) se um outro c.delete (f [y] [x])
r = 1
def R (e): r global; 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. depois (99, L)
 se r: retornar
 g = cópia.deepcopia (f)
 para y em z (F):
	para x em z (F):
	 n = 8
	 para j em z (-1,2):
		para i em z (-1,2):
		 se i ou j: n- = não g [(y + j)% F] [(x + i)% F]
	 se 1 <n <4:
		se n == 3e não g [y] [x]: p (x, y, 1)
	 mais: p (x, y, 0)
EU()
T.mainloop ()

E aqui está uma versão onde você pode arrastar o mouse para desenhar. Os gráficos são um pouco mais agradáveis.

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

Isso não segue as regras do jogo da vida corretamente.
precisa saber é o seguinte

11
@StevenRumbalski: Ah, sério?
Oleh Prypin

2
realmente. Você tem um erro de recuo na sua segunda versão. A seção que começa com if 1<n<4:deve ser recuada no mesmo nível quefor j in z(-1,2):
Steven Rumbalski 23/08

2

Python 2, 456 bytes

Embora eu saiba que este é um post antigo, não pude deixar de tentar. O quadro inicial pode ter qualquer tamanho, desde que você desenhe uma borda ao redor e tenha um espaço extra na última linha.

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 (observe o espaço extra na última linha)

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

Como executar

python Golf.py < input.txt

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

^, Você esqueceu um, 1 if=> 1if.
Zachary

2

Em processamento 270.261 249 bytes

Grade é os 100 * 100 pixels da tela, a entrada vem na forma de uma imagem 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();
}

captura de tela


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

ou espaçados:

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

Clique no campo para adicionar células vivas. Clique fora do campo para executá-lo.

Experimente online!

insira a descrição da imagem aqui


1

Postscript 529 515

Começou com o exemplo do código Rosetta . Invoque com um argumento de nome de arquivo ( gs -- gol.ps pulsar), o arquivo que contém 20 * 20 números binários (separados por espaço). Loop infinito: prancheta, aguarde enter, calcule a próxima geração.

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

Espaçado, com alguns comentários da pilha (apenas os que eu precisava).

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

arquivo de dados 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

Desculpe Griffin, eu simplesmente não conseguia olhar para o seu código e não reescrevê-lo um pouco ... tive que raspar dois caracteres, mas valeu a 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}

Mas, como eles dizem, é mais fácil pedir perdão do que permissão ...;)


1

Oitava (153)

o mesmo que Matlab por DenDenDo no Shortest Game of Life , mas teve que mudar imshow para 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 bytes

Apenas 6 anos atrasado.

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"

Você pode executá-lo como:

python gol.py
0000000
0001000
0000100
0011100
0000000
0000000
0000000

Onde os 0s e 1s representam células mortas e vivas, uma nova linha extra no final inicia a execução.

As grades devem ser quadradas.

É mais fácil de executar do que o python mais curto, suporta grades de qualquer tamanho e fica bonito quando executado.

Também é 100 bytes a mais, então é isso.


0

PHP, 201 bytes (não testado)

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;

Corra com -nr.

demolir

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.