A vida pode ser colorida!


30

Cada célula de um autômato celular semelhante à vida precisa apenas de um bit para representá-lo, pois só pode estar vivo ou morto. Isso significa que existem apenas duas cores; muito chato.

Imagens normais têm 24 bits por pixel (8 em cada um dos RGB). Isso significa que, em uma imagem normal com pixels como células, você pode simular 24 jogos reais ao mesmo tempo!

Desafio

Sua tarefa é escrever um programa que aplicará uma geração das regras de um autômato celular realista a uma imagem de profundidade de 24 bits (em qualquer formato conhecido que você queira) e produzir a imagem resultante.

Cada uma das 24 camadas usará o mesmo conjunto de regras realista, estritamente dentro de sua própria camada. As 24 camadas não interagem umas com as outras.

Além disso

  • Zeros são células mortas e outras são células vivas.
  • As condições de contorno são periódicas (formando um toro).
  • Quaisquer dimensões da imagem devem funcionar.

Entrada / Saída

Seu programa precisa receber 3 argumentos, via stdin ou linha de comando (ou o equivalente mais próximo do seu idioma):

  1. O nome do arquivo de imagem de entrada.
  2. Uma sequência de dígitos de 0 a 8 em ordem crescente que indica quando novas células nascem:
    • Se o dígito d está na corda, em seguida, as células mortas ganham vida quando eles têm d vizinhos vivos.
    • Exemplo: 3é Vida normal - Células mortas com exatamente 3 vizinhos vivos ganham vida.
  3. Uma sequência de dígitos de 0 a 8 em ordem crescente que indica quando as células existentes sobrevivem:
    • Se o dígito d estiver na cadeia, as células vivas com d vizinhos vivos sobreviverão até a próxima geração, caso contrário, elas morrerão.
    • Exemplo: 23é normal Vida - Somente células com exatamente 2 ou 3 vizinhos sobrevivem à próxima rodada.

Observe que o bairro de Moore é sempre usado. Leia isto ou isto para obter mais informações sobre o que define com precisão um autômato real e muitos conjuntos de regras interessantes.

A imagem de saída de uma geração depois deve ser exibida ou salva como out.png( bmpou o que seja).

Submissão

O código mais curto em bytes vence.

Você está exigido para incluir pelo menos uma imagem de teste e suas três gerações subseqüentes imediatos para algum conjunto de regras não-trivial. Use seu avatar e as regras normais da vida se você não conseguir pensar em nada melhor.

Se você quiser, pode usar esta pistola Gosper Glider onde os únicos bits vivos estão na camada verde 128 (é certo que funcionará na vida normal):

pistola de planador

A publicação de sequências interessantes ou mesmo animações é altamente recomendável.


1
Eu acho que é uma duplicata - as únicas partes novas estão lendo em outro formato de arquivo e dividindo as camadas - ambas são básicas e não são um desafio por si mesmas.
Howard

1
@ Howard Mas você não está interessado em ver as imagens?

3
Sim. PPCG.SE é um lugar de dor e agonia, não imagens divertidas e bonitas . Se ele faz da idéia do bônus um requisito, certamente a pergunta deve ser original o suficiente?
Flonk

3
O interesse claro da comunidade é que os programas não sejam copiados e colados com pequenas alterações nas respostas a outras perguntas. Este site não funciona com base em "Eu acho que pode ser divertido, então está tudo bem". Isso é 4chan.
Peter Taylor

4
@ Howard Eu não acho que isso conta mais como duplicado. Certamente se codegolf.stackexchange.com/questions/34505/simulate-rule-110 e codegolf.stackexchange.com/questions/4370/… podem coexistir, isso não é uma duplicata.
Hobbies de Calvin

Respostas:


16

MATLAB: 275

Meu favorito dos parâmetros que tentei é o seguinte 45678, 568após uma desintegração gradual, resultando em um céu de estrelas cintilantes. Esta imagem descreve "a desintegração da persistência da memória".

Código não produtor de gif (aceita PNG sem extensão):

B = input('B', 's') - 48;
S = input('S', 's') - 48;
f0 = input('file: ', 's');
frames = 60;

f = sprintf('%s.png',f0);
fout = sprintf('%s.gif',f0);
first = 1;
img = imread(f);
for i = 1:60
    out = img * 0;
    [r, c, turd] = size(img);
    for b=0:7
        bimg = ~~bitand(img,2^b);
        pimg = [bimg,bimg,bimg;bimg,bimg,bimg;bimg,bimg,bimg];
        fun = @(ro,co) pimg(r+ro:r+r+ro-1,c+co:c+c+co-1,:);
        sum = fun(0,0)+fun(0,1)+fun(0,2)+fun(1,0)+fun(1,2)+fun(2,0)+fun(2,1)+fun(2,2);
        bnew = uint8(bimg & ismember(sum,S) | ~bimg & ismember(sum, B));
        out = out + 2^b * bnew;
    end
    %imwrite(out,'out.png');
       if first
           [img1,img2] = rgb2ind(img,256);
           imwrite(img1,img2,fout,'gif','Loop',Inf);
          imwrite(img1,img2,fout,'gif','WriteMode','append');
           first = 0;
       end
       img = out;
       [img1,img2] = rgb2ind(img,256);
       imwrite(img1,img2,fout,'gif','WriteMode','append');%,'DelayTime', 2*delay);
end

Código de golfe que aceita um nome de arquivo completo (que pode ser GIF, JPEG e talvez outros itens) e grava em out.png:

I=@()input('','s');B=I();S=I();i=imread(I());o=0;[r,c,t]=size(i);for b=0:7
g=~~bitand(i,2^b);p=repmat(g,3);F=@(z,Z)p(r+z:r+r+z-1,c+Z:c+c+Z-1,:);M=@(A)ismember(F(0,0)+F(0,1)+F(0,2)+F(1,0)+F(1,2)+F(2,0)+F(2,1)+F(2,2),A-48);o=o+2^b*uint8(g&M(S)|~g&M(B));end
imwrite(o,'out.png')

Um fato descoberto anteriormente é que os parâmetros 12, 1podem ser utilizados para gerar um Sierpinsky tapete do tipo fractal. Aqui está um com um ponto de semente colocado aleatoriamente em cada bit:


14

Mathematica, 359

i=InputString;f=Transpose;b=(p=FromDigits/@Characters@#&)@i[];s=p@i[];Map[FromDigits[#,2]&/@#~ArrayReshape~{3,8}&,f[(g=#;{#,Total[g~RotateRight~#&/@Drop[Join@@Table[{i,j},{i,-1,1},{j,-1,1}],{5}],1]}~f~{3,1,2}/.{l_,n_}:>Boole[l<1&&!b~FreeQ~n||l>0&&!s~FreeQ~n])&/@Apply[Join,IntegerDigits[ImageData[Import@i[],y="byte"],2,8],{2}]~f~{2,3,1},{3,1,2}],{2}]~Image~y

Estou recebendo informações de solicitações de sequência de caracteres na ordem (1) regras de nascimento, (2) regras de sobrevivência, (3) nome do arquivo e estou exibindo o resultado diretamente no Mathematica.

Isso deve ser capaz de lidar com os formatos mais populares, desde que o arquivo realmente tenha profundidade de 24 bits.

Aqui está uma versão um pouco não-destruída:

i = InputString;
f = Transpose;
b = (p = FromDigits /@ Characters@# &)@i[];
s = p@i[];
Map[
  FromDigits[#,2] & /@ #~ArrayReshape~{3, 8} &,
  f[
   (
      g = #;
      {#, 
         Total[g~RotateRight~# & /@ 
           Drop[Join @@ Table[{i, j}, {i, -1, 1}, {j, -1, 1}], {5}], 
          1]}~f~{3, 1, 2} /. {l_, n_} :> 
        Boole[l < 1 && ! b~FreeQ~n || l > 0 && ! s~FreeQ~n]
      ) & /@ 
    Apply[Join, 
      IntegerDigits[ImageData[Import@i[], y = "byte"], 2, 8], {2}]~
     f~{2, 3, 1},
   {3, 1, 2}
   ],
  {2}
  ]~Image~y

Aqui estão dois exemplos usando o avatar de Rainbolt :

Rainbolt

20 gerações usando o Game of Life padrão [3,23]:

insira a descrição da imagem aqui

20 gerações usando [456,34567]:

insira a descrição da imagem aqui

E aqui está um GIF das 200 primeiras gerações da última regra. O GIF pula cada terceiro quadro, porque não poderia compactá-lo abaixo de 2 MB:

insira a descrição da imagem aqui


2
que regra interessante
proud haskeller

10

Python 2, 427

Para quem não tem Mathematica;)

import Image as I
t=raw_input
r=range
A=I.open(t())
G=map(int,t())
S=map(int,t())
w,h=A.size
B=I.new('RGB',(w,h))
A=[[map(int,("{:08b}"*3).format(*A.load()[x,y]))for y in r(h)]for x in r(w)]
for x in r(w):
 for y in r(h):
  p=''
  for i in r(24):
    c=A[x][y][i]
    n=sum(A[(x+k-1)%w][(y+j-1)%h][i]for j in r(3)for k in r(3))-c
    p+=str(~~[n in G,n in S][c])
  B.load()[x,y]=tuple(int(p[i*8:i*8+8],2)for i in r(3))
B.save('out.bmp')

Ele solicita o nome do arquivo, os casos de nascimento e os casos de sobrevivência. Portanto, para as regras normais da vida, você pode inserir test.bmp, então 3, então 23(sem aspas ou qualquer coisa necessária).

Usei a formatação de string para indexar e recombinar os bits de cor, embora eu receie que provavelmente não seja o ideal.

Note que é bem lento.

Exemplo

Alta vida e excelente arte misturam-se, certo? (Regra 36/ 23.)

Mona Lisa Original geração 1 Original / Geração 1

geração 2 geração 3 Geração 2 / Geração 3


6

Java, 1085 bytes

import java.awt.image.*;import java.io.*;import javax.imageio.*;class F{static int n(boolean[][][]a,int x,int y,int z){int k=0;for(X=Math.max(x-1,0);X<Math.min(x+2,w);X++)for(Y=Math.max(y-1,0);Y<Math.min(y+2,h);Y++)if(a[X][Y][z])k++;return k-(a[x][y][z]?1:0);}static int p(String k){return Integer.parseInt(k,2);}static int w,h,x,y,z,X,Y;public static void main(String[]a)throws Exception{BufferedImage i=ImageIO.read(new File(a[0]));w=i.getWidth();h=i.getHeight();boolean[][][]G=new boolean[w][h][24];for(x=0;x<w;x++)for(y=0;y<h;y++){String k="".format("%24s",Integer.toBinaryString(0xFFFFFF&i.getRGB(x,y)));for(z=0;z<24;z++){G[x][y][z]=k.charAt(z)>48;}}for(x=0;x<w;x++)for(y=0;y<h;y++){String r="",g="",b="",k;for(z=0;z<8;){k=""+n(G,x,y,z);r+=(-1!=(G[x][y][z++]?a[1].indexOf(k):a[2].indexOf(k)))?1:0;}for(;z<16;){k=""+n(G,x,y,z);g+=(-1!=(G[x][y][z++]?a[1].indexOf(k):a[2].indexOf(k)))?1:0;}for(;z<24;){k=""+n(G,x,y,z);b+=(-1!=(G[x][y][z++]?a[1].indexOf(k):a[2].indexOf(k)))?1:0;}i.setRGB(x,y,new java.awt.Color(p(r),p(g),p(b)).getRGB());}ImageIO.write(i,"png",new File("out.png"));}}

Exemplos (regra 368/245):

Gen 0:

insira a descrição da imagem aqui

Gen 1:

insira a descrição da imagem aqui

Gen 2:

insira a descrição da imagem aqui

Gen 3:

insira a descrição da imagem aqui

Gen 4:

insira a descrição da imagem aqui

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.