Implementar o jogo da vida em 3D


17

O desafio é encontrar a menor implementação do jogo da vida em 3D ( exemplo ). Estas são as regras:

Células (neste caso, cubos) com apenas 1 ou menos vizinhos morrem, como se fossem solitários.
Se exatamente 5 células cercam uma célula vazia, elas se reproduzem e a preenchem.
Se uma célula tem 8 ou mais vizinhos, morre por superlotação.

Faça pelo menos um 10x10x10, onde as camadas são produzidas individualmente assim:

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 X 0 0 X 0 0 0 0 0
0 0 X X X 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

Obviamente, uma simulação 3D gráfica também é aceita.
A posição inicial pode ser codificada permanentemente, mas deve funcionar se for alterada para qualquer posição inicial. Ele deve poder calcular qualquer quantidade de gerações e o usuário deve poder solicitar manualmente a próxima geração.

O menor código em caracteres vence!

Fiz minha própria implementação para qualquer tamanho (cubo): http://jensrenders.site88.net/life3D.htm Você pode usar isso para testar e pode basear seu código no meu, embora eu não tenha comentado .


11
Implicada a tag code-golf da sua declaração, encontre a implementação mais curta . Por favor, verifique se é o que você deseja. Você também deve fornecer alguns detalhes sobre como inserir, quantos ciclos, animação sim / não, ... porque é essencial que o code-golf tenha uma especificação robusta.
— 287 Howard

@ Howard eu adicionei mais algumas especificações, e sim, esqueci a tag code-golf;) obrigado por isso.
— Jens processa

@ PeterTaylor Sim exatamente 5, eu vou editá-lo.
— Jens Processa

Eu adicionaria detalhes sobre o formato de saída (por exemplo, cada célula deve ser separada por um espaço, como no seu exemplo, uma nova linha entre cada camada de grade da saída, as células vivas e mortas devem ser representadas por caracteres diferentes, e esses devem ser caracteres visíveis .) Além disso, lembre-se de que, se enquadrado como código-golfe, é improvável que você obtenha simulações gráficas.
— Jonathan Van Matre

Você realmente quis proibir todas as brechas discutidas nesse meta thread, ou apenas aquelas que atendem aos critérios de (des) aprovação (pontuação de +5, pelo menos duas vezes mais votos positivos e negativos)? Porque eu tenho certeza que eu poderia totalmente pensar em algumas interessantes "brechas" bonitas para discutir ... ;-)
— Ilmari Karonen

Respostas:


14

Mathematica - 120 bytes

g=CellularAutomaton[{(l=Flatten@#;c=l[[14]];n=Total@Drop[l,{14}];Which[n<2||n>7,0,n==5||c==1,1,0<1,0])&,{},{1,1,1}},##]&

Certamente não é um candidato à vitória, mas essa não era minha intenção. Além disso, isso provavelmente poderia ser reduzido significativamente, apenas descobrindo o número da regra. Eu realmente queria escrever uma visualização (embora eu tenha certeza de que já existem toneladas por aí). Aqui vamos nos):

animateGol3d[size_, i_, n_] := 
  ListAnimate[
    Graphics3D[
      Cuboid /@ Position[#, 1], 
      PlotRange -> {{0, size}, {0, size}, {0, size}} + 1
    ] & /@ g[i, n]
  ];

E depois de experimentar várias condições iniciais, obtive coisas como as seguintes:

insira a descrição da imagem aqui

E aqui está um com um tamanho de grade de 20x20x20. Demorou alguns segundos para simular e renderizar:

insira a descrição da imagem aqui

A propósito, isso pressupõe condições de contorno periódicas.


Aqueles realmente estão entrando em um estado de equilíbrio ou a animação está parando? No primeiro caso, você me deu algumas idéias puras ...
— Kroltan

11
@ Kroltan Já faz um tempo, mas tenho certeza de que eles estavam alcançando o equilíbrio.
— Martin Ender

11
Bom obrigado. Fatias individuais do equilíbrio parecem muito com o mapa da sala, por exemplo, um jogo parecido com um rougel.
— Kroltan

12

APL, 46

Demorei algum tempo, mas reduzi para 46 caracteres:

{(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵}

Essa é uma função que pega uma matriz 3D booleana de qualquer tamanho e calcula a próxima geração, de acordo com as regras fornecidas. As condições de contorno não foram especificadas, então optei por envolver o outro lado, como no espaço toroidal.

Explicação

{                           ⊂⍵}   Take the argument matrix and enclose it in a scalar
               (i←2-⍳3)           Prepare an array with values -1 0 1 and call it i
                       ⌽[2]¨      Shift the matrix along the 2nd dim. by each of -1 0 1
           i∘.⊖                   Then for each result do the same along the 1st dimension
       i∘.⌽                       And for each result again along the 3rd dimension
 m←⊃+/,                           Sum element-wise all 27 shifted matrices and call it m

O resultado intermediário mé uma matriz com a mesma forma da matriz original, que conta para cada elemento quantas células estão vivas em sua vizinhança 3 × 3 × 3, incluindo a si mesma. Então:

           |5.5-m   For each element (x) in m, take its distance from 5.5
       ⍵∧3>         If that distance is <3 (which means 3≤x≤8) and the original cell was 1,
 (5=m)∨             or if the element of m is 5, then the next generation cell will be 1.

Exemplo

Defina uma matriz aleatória 4 × 4 × 4 com cerca de 1/3 de células = 1 e calcule sua 1ª e 2ª geração. A ⊂[2 3]parte da frente é apenas um truque para imprimir os planos horizontalmente em vez de verticalmente:

      ⊂[2 3] m←1=?4 4 4⍴3
 1 0 0 0  1 0 1 0  1 0 1 0  0 0 0 1 
 1 1 0 0  0 0 0 0  0 0 0 1  1 0 1 0 
 0 0 0 0  0 1 0 0  0 0 0 0  0 0 1 0 
 1 1 0 0  0 0 0 1  1 0 0 1  0 0 1 0 
      ⊂[2 3] {(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵} m
 0 0 0 0  0 0 1 0  1 0 1 0  0 0 0 0 
 1 0 0 0  0 0 1 0  0 0 0 0  1 0 1 0 
 0 0 0 0  0 1 0 0  0 0 0 0  0 0 1 0 
 1 1 0 0  0 0 0 0  1 0 0 0  0 0 1 0 
      ⊂[2 3] {(5=m)∨⍵∧3>|5.5-m←⊃+/,i∘.⌽i∘.⊖(i←2-⍳3)⌽[2]¨⊂⍵}⍣2⊢ m
 0 0 1 0  1 0 1 0  1 0 1 0  0 0 0 0 
 1 0 1 0  0 0 1 1  0 0 0 0  1 0 1 0 
 1 0 0 0  1 1 0 0  0 0 1 0  1 0 1 0 
 1 1 1 0  1 0 0 1  1 0 1 0  0 0 1 0 

+1 Resposta muito boa! e, de fato, os limites não foram especificados; portanto, é permitido contornar.
— Jens Processa

9

J - 42 char

Estamos assumindo uma placa toroidal (em volta) nas três dimensões. A exibição automática de resultados de J parece seguir as especificações de saída, usando 1para células vivas e 0mortas. Esse código funciona em placas de qualquer largura, comprimento e altura (podem ser 10x10x10, 4x5x6 etc.).

(((1&<*<&8)@-*]+.5=-)~[:+/(,{3#<i:1)|.&><)

Segue uma explicação:

  • ,{3#<i:1 - Subexpressão da lista de compensações para a célula e todos os seus vizinhos.
    • <i:1 - A lista de números inteiros entre 1 e -1, inclusive.
    • ,{3#- Faça três cópias da lista ( 3#) e leve o produto cartesiano ( ,{).
  • (,{3#<i:1)|.&><- Para cada conjunto de deslocamentos 3D, mude a matriz. A um custo de 3 caracteres, você pode mudar |.&>para |.!.0&>não ter wrap-around.
  • [:+/ - Soma todas as tábuas deslocadas.
  • ((1&<*<&8)@-*]+.5=-)~- O verbo externo longo era um gancho, de modo que ele recebe o quadro à esquerda e à direita, e o lado à direita que estivemos mudando e somando. A ~troca é feita por esse verbo interno.
    • 5=- - 1 em cada célula em que a soma das placas deslocadas menos a placa original (ou seja, a contagem de vizinhos) é igual a 5 e 0 em todas as outras.
    • ]+. - Lógico OU acima com a placa original.
    • (1&<*<&8) - 1 se o número estiver sendo comparado entre 1 e 8 exclusivo, 0 caso contrário.
    • (1&<*<&8)@-* - Compare (como acima) a contagem de vizinhos e multiplique (ou seja, AND lógico quando o domínio é apenas 1 ou 0) o resultado OU lógico por isso.

O uso é como no APL, basta aplicar a função ao quadro inicial para cada etapa. J tem um operador de energia funcional ^:para facilitar isso.

   life =: (((1&<*<&8)@-*]+.5=-)~[:+/(,{3#<i:1)|.&><)  NB. for convenience
   board =: 1 = ?. 4 4 4 $ 4  NB. "random" 4x4x4 board with approx 1/4 ones
   <"2 board  NB. we box each 2D plane for easier viewing
+-------+-------+-------+-------+
|0 0 0 0|1 1 0 0|0 1 0 0|0 0 1 0|
|0 1 0 0|0 0 0 0|0 0 0 1|1 0 0 0|
|0 0 0 0|0 0 1 0|0 1 0 0|0 0 0 1|
|1 1 0 0|1 0 0 0|0 0 0 1|0 1 1 0|
+-------+-------+-------+-------+
   <"2 life board
+-------+-------+-------+-------+
|0 0 0 0|0 1 0 1|0 1 0 0|0 0 1 0|
|1 1 1 1|0 0 0 0|0 0 0 1|1 1 0 0|
|0 0 0 0|0 0 1 1|0 1 0 0|0 0 0 1|
|1 0 0 0|1 0 0 1|0 0 0 1|0 1 1 1|
+-------+-------+-------+-------+
   <"2 life^:2 board  NB. two steps
+-------+-------+-------+-------+
|0 0 0 0|0 1 0 0|0 1 0 0|0 0 0 0|
|0 1 0 0|0 0 0 0|0 0 0 1|0 1 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 1 1 1|
+-------+-------+-------+-------+
   <"2 life^:3 board  NB. etc
+-------+-------+-------+-------+
|0 1 0 0|1 1 1 0|0 1 0 0|0 1 0 0|
|0 1 0 0|1 0 1 0|1 0 1 0|1 1 1 0|
|1 0 0 0|0 0 0 0|0 1 0 0|0 1 0 0|
|0 0 1 0|0 0 0 0|0 1 0 0|0 1 1 0|
+-------+-------+-------+-------+

Eu digo "aleatório" porque o ?.primitivo fornece resultados aleatórios reproduzíveis usando sempre uma semente fixa. ?é o verdadeiro RNG.


Maldição J e seu |.verbo imundo !! Bom trabalho.
— Tobia
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.