Jogo da vida e fadiga

10

O Jogo da Vida e Fadiga de Stewie é bastante semelhante ao Jogo da Vida de Conway, mais famoso .


O universo do Jogo da Vida e Fadiga de Stewie (GoLF) é uma grade ortogonal bidimensional infinita de células quadradas, cada uma das quais está em um dos três estados possíveis: vivo, morto ou cansado. Cada célula interage com seus oito vizinhos, que são as células que são horizontal, vertical ou diagonalmente adjacentes. A cada etapa, ocorrem as seguintes transições:

  • Qualquer célula viva com menos de dois vizinhos vivos morre, como se causada por subpopulação.
  • Qualquer célula viva com dois ou três vizinhos vivos vive para a próxima geração.
  • Qualquer célula viva com mais de três vizinhos vivos morre, como se por superpopulação.
  • Qualquer célula morta com exatamente três vizinhos vivos se torna uma célula viva, como se fosse reprodução.
  • Qualquer célula que esteja viva por duas gerações consecutivas morre, como se por fadiga. Não pode despertar para a vida novamente até a próxima geração
  • Qualquer célula que esteja fora dos limites da grade de entrada está morta, como se tivesse caído de um penhasco.

Desafio:

Seu desafio é pegar uma grade de dimensões n-por-m representando o estado inicial de um GoLF e um número inteiro p , e gerar o estado do jogo após p gerações.

Regras:

  • Os formatos de entrada e saída são opcionais, mas as grades de entrada / saída devem ter a mesma representação
  • Você pode escolher qualquer símbolo imprimível para representar células vivas e mortas (usarei 1para células vivas e 0células mortas).
  • Você pode escolher se possui 0 ou 1 indexado. Nos exemplos, p=1significa o estado após uma etapa.
  • O código mais curto em cada idioma vence
  • Função interna para automação celular é permitida

Casos de teste:

Nos exemplos, incluí apenas a grade de entrada na entrada, não p . Eu forneci saídas para vários valores de p . Você deve emitir apenas a grade que acompanha uma determinada entrada p .

Input:
0   0   0   0   0
0   0   1   0   0
0   0   1   0   0
0   0   1   0   0
0   0   0   0   0

--- Output ---
p = 1
0   0   0   0   0
0   0   0   0   0
0   1   1   1   0
0   0   0   0   0
0   0   0   0   0

p = 2
0   0   0   0   0
0   0   1   0   0
0   0   0   0   0
0   0   1   0   0
0   0   0   0   0

p = 3 -> All dead
---

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

--- Output ---
p = 1
0   0   0   0   0   0
1   0   1   0   0   0
0   1   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

p = 2
0   0   0   0   0   0
0   0   0   0   0   0
1   0   0   0   0   0
0   1   1   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0

p = 3
0   0   0   0   0   0
0   0   0   0   0   0
0   1   0   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0

p = 4 -> All dead
Input
0   1   1   0   1   1   0
1   1   0   1   1   1   1
0   1   0   0   0   1   0
0   0   0   1   1   0   1
1   0   0   1   0   1   1
0   0   1   1   0   1   1
1   1   0   0   0   0   1

--- Output ---
p = 1
1   1   1   0   0   0   1
1   0   0   1   0   0   1
1   1   0   0   0   0   0
0   0   1   1   0   0   1
0   0   0   0   0   0   0
1   0   1   1   0   0   0
0   1   1   0   0   1   1

p = 2
1   0   0   0   0   0   0
0   0   0   0   0   0   0
1   0   0   1   0   0   0
0   1   1   0   0   0   0
0   1   0   0   0   0   0
0   0   0   0   0   0   0
0   0   1   1   0   0   0   

p = 3
0   0   0   0   0   0   0
0   0   0   0   0   0   0
0   1   1   0   0   0   0
1   1   0   0   0   0   0
0   1   1   0   0   0   0
0   0   1   0   0   0   0
0   0   0   0   0   0   0

p = 4
0   0   0   0   0   0   0
0   0   0   0   0   0   0
1   1   1   0   0   0   0
1   0   0   0   0   0   0
1   0   1   0   0   0   0
0   1   1   0   0   0   0
0   0   0   0   0   0   0

p = 5
0   0   0   0   0   0   0
0   1   0   0   0   0   0
1   0   0   0   0   0   0
0   0   1   0   0   0   0
1   0   0   0   0   0   0
0   1   0   0   0   0   0
0   0   0   0   0   0   0

p = 6
0   0   0   0   0   0   0
0   0   0   0   0   0   0
0   1   0   0   0   0   0
0   1   0   0   0   0   0
0   1   0   0   0   0   0
0   0   0   0   0   0   0
0   0   0   0   0   0   0

p = 7
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   0
0   0   0   0   0   0   0
0   0   0   0   0   0   0
0   0   0   0   0   0   0

p = 8
0   0   0   0   0   0   0
0   0   0   0   0   0   0
0   1   0   0   0   0   0
0   0   0   0   0   0   0
0   1   0   0   0   0   0
0   0   0   0   0   0   0
0   0   0   0   0   0   0

p = 9 -> All dead

Sim, estou ciente de que todas as sementes iniciais não terminarão em todas as células mortas.

Stewie Griffin
fonte
Talvez você deva esclarecer que o item de transição 5 é aplicado "ao mesmo tempo" que os itens 1--4, ou seja, é baseado no estado antes de aplicar 1--4
Luis Mendo
2
" células, cada uma das quais em um dos dois estados possíveis, vivos ou mortos " parece uma definição deliberadamente perversa, uma vez que a regra de fadiga posterior só pode ser expressa em um autômato finito padrão, fazendo com que cada célula tenha três estados (mortos, recentemente vivo, vivo por duas gerações consecutivas)
Peter Taylor
11
Eu tenho uma regra de Golly para isso, se alguém quiser.
CalculatorFeline
6
Jogando GoD, não é?
Adám

Respostas:

3

MATL , 34 30 25 bytes

5 bytes removidos graças a uma sugestão de @CalculatorFeline !

0ii:"wy*~wt3Y6QZ+5:7mb*]&

Experimente online!

As entradas são uma matriz e um número. A matriz usa ;como separador de linhas. As matrizes para os três casos de teste são inseridas como

[0 0 0 0 0; 0 0 1 0 0; 0 0 1 0 0; 0 0 1 0 0;0 0 0 0 0]
[0 1 0 0 0 0; 0 0 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 1 1 0 1 1 0; 1 1 0 1 1 1 1; 0 1 0 0 0 1 0; 0 0 0 1 1 0 1; 1 0 0 1 0 1 1; 0 0 1 1 0 1 1; 1 1 0 0 0 0 1]

Explicação

0     % Push 0. This represents the generation previous to the input one. Actually
      % This should be an array of zeros, but thanks to broadcasting it is
      % equivalent (and saves bytes)
i     % Input: array with starting generation
i     % Input: number of iterations, p.
      % STACK (bottom to top): 0, array with initial generation, p
:"    % Do the following p times
      %   STACK: previous gen, current gen
  wy  %   Swap, duplicate from below
      %   STACK: current gen, previous gen, current gen
  *~  %   Multiply element-wise, negate. This creates a mask of cells that do not 
      %   die of fatigue (they were 0 in the current or in the previous generation)
      %   STACK: current gen, fatigue mask
  wt  %   Swap, duplicate
      %   STACK: Fatigue mask, current gen, current gen
  3Y6 %   Push predefined literal: 8-neighbourhood: [1 1 1; 1 0 1; 1 1 1]
      %   STACK: Fatigue mask, current gen, current gen, 8-neighbourhood
  Q   %   Add 1 element-wise. This gives [2 2 2; 2 1 2; 2 2 2], which will be
      %   used as convolution kernel. Active cells with 2 neighbours will give 5;
      %   inactive cells with 3 neighbours will give 6; and active cells with 3
      %   neighbours will give 7
      %   STACK: Fatigue mask, current gen, current gen, convolution kernel
  Z+  %   2D convolution, keeping size
      %   STACK: Fatigue mask, current gen, convolution result
  5:7 %   Push array [5 6 7]
  m   %   Ismember, element-wise. Cells that give true will survive, unless fatigued
      %   STACK: Fatigue mask, current gen, cells that can survive
  b   %   Bubble up
      %   STACK: Current gen, cells that can survive, fatigue mask
  *   %   Multiply element-wise. This tells which cells survive considering fatigue.
      %   The result is the new generation
      %   STACK: "Current" gen which now becomes old, "new" gen which now becomes
      %   current
]     % End 
&     % Specify that implicit display will show only top of the stack
Luis Mendo
fonte
11
Você pode explicar 3Y6com mais detalhes? Além disso, se o elemento do meio do kernel fosse .5, você poderia verificar o CGOL apenas 2<value<4. Pode ajudar.
CalculatorFeline
@CalculatorFeline Essa é uma sugestão muito boa, obrigado! Isso levou a economizar 5 bytes, usando o dobro da máscara e testando-a 5<=value<=7. Quanto a 3Y6, é apenas um literal predefinido. Também 1Y6tem o bairro 4
Luis Mendo
11
Hã. Isso realmente funcionou. Arrumado.
CalculatorFeline
3

APL (Dyalog Classic 16.0) , 59 bytes

⌊{((3∊⌊{⍵,⍵-c}+/,⍵)∧.1>1|c)×(.1×c)+1c2 2⌷⍵}⎕U233A 3 3⍣⎕⊢⎕

Experimente online! (emulado no Classic 15.0)


APL (Dyalog Unicode 16.0) , 85 bytes

⌊{((3∊⌊{⍵,⍵-c}+/,⍵)∧.1>1|c)×(.1×c)+1c2 2⌷⍵}⌺3 3⍣⎕⊢⎕

Experimente online! (emulado no Unicode 15.0)


Solicita grade e, em seguida, p . Imprime a nova grade após p gerações.

Observe que isso usa a nova primitiva (Estêncil) que não está incluída no conjunto de caracteres Clássico, portanto, uma versão mais curta e uma versão com menos bytes.

Explicação a seguir…

Adão
fonte
Formato de exibição da APL é bom :-)
Luis Mendo
@LuisMendo Na verdade, não são "APL's", mas o intérprete faz um retorno de chamada para essa função APL quando deseja produzir. A função analisa o que queremos produzir e modifica-o de acordo. A explicação para a displayfunção está aqui .
Adám
3

Golly RuleLoader, 295 bytes

@RULE Y
@TABLE
n_states:3
neighborhood:Moore
symmetries:permute
var z={1,2}
var y=z
var x=z
var w=z
var u=z
var a={0,z}
var b=a
var c=a
var d=a 
var e=a
var f=a
var g=a 
var h=a
0,z,y,x,0,0,0,0,0,1
z,a,0,0,0,0,0,0,0,0
z,y,x,w,u,a,b,c,d,0
2,a,b,c,d,e,f,g,h,0
1,a,b,c,d,e,f,g,h,2
@COLORS
2 255 0 0

A grade de entrada deve ser colada, os limites estão no nome da regra (por exemplo, 5* 3é Y:P5,3), pressione espaço para avançar.

CalculatorFeline
fonte
2

Java 8, 333 bytes

int[][]G(int p,int[][]s){for(int h=s.length,w=s[0].length,y,x,n,a,b,t[][]=new int[h][w],i=0;i++<2*p;)for(y=0;y<h;++y)for(x=0;x<w;++x)if(i%2>0){for(n=0,a=y-2;++a<y+2;)for(b=x-2;++b<x+2;)n+=a>=0&a<h&b>=0&b<w&(a!=y|b!=x)&&s[a][b]>0?1:0;t[y][x]=s[y][x]<1?n==3?1:0:n<2|n>3|s[y][x]>1?0:2;}else s[y][x]=i==2*p&t[y][x]>1?1:t[y][x];return s;}

Explicação:

int[][]G(int p,int[][]s){
    for(int h=s.length,w=s[0].length,y,x,n,a,b,t[][]=new int[h][w],       //height, width, vars, temp array
            i=0;i++<2*p;)                                                 //for 2*generations: 1. calculate in temporary t, 2. copying to s
        for(y=0;y<h;++y)                                                  //for each row
            for(x=0;x<w;++x)                                              //for each column
                if(i%2>0){                                                //1. calculate
                    for(n=0,a=y-2;++a<y+2;)                               //n = number of alive cells around [y][x]. row above, at and below y
                        for(b=y-2;++b<y+2;)                               //column left, at and right of x
                            n+=a>=0&a<h&b>=0&b<w&(a!=y|b!=x)&&s[a][b]>0?1:0;    //if within bounds and not the cell itself, add 1 if alive.
                    t[y][x]=s[y][x]<1?n==3?1:0:n<2|n>3|s[y][x]>1?0:2;     //save next state in temporary, depending on rules. alive cells become 2.
                }
                else                                                      //2. copy temporary t to s
                    s[y][x]=i==2*p&t[y][x]>1?1:t[y][x];                   //if last generation, replace 2 by 1
    return s;
}
Sebastian Matschke
fonte