Simule o autômato celular Wireworld

24

O Wireworld é um autômato celular projetado para se parecer com elétrons que fluem através de fios. Sua mecânica simples permite a construção de circuitos digitais. Ele até permitiu a construção de um computador inteiro .

Sua missão é criar a menor implementação do Wireworld no seu idioma preferido.

Cada célula na grade possui um dos quatro estados. Os quatro estados são "em branco", "cobre", "cabeça de elétron" ou "cauda de elétron".

  • Uma célula em branco sempre permanecerá uma célula em branco
  • Uma cabeça de elétron sempre se tornará uma cauda de elétrons
  • Uma cauda de elétron sempre se tornará cobre
  • Uma célula de cobre se tornará uma cabeça de elétrons se exatamente um ou dois de seus oito vizinhos forem cabeças de elétrons, caso contrário, permanecerá cobre

Esta competição terá um estilo semelhante ao da competição Shortest Game of Life , mas com algumas alterações.

  • A grade deve ter pelo menos 40 por 40 células
  • As bordas da grade NÃO devem ser dobradas (não um toro). Trate as células fora do campo como sendo constantemente "em branco".
  • Deve ser possível que os usuários insiram sua própria configuração inicial.
  • Olhar fixamente para telas em branco não é divertido. O programa deve exibir visualmente a simulação enquanto está em execução.

Isso é código de golfe, o menor número de bytes vence.

PhiNotPi
fonte

Respostas:

6

APL, Dyalog (131)

{h t c←1↓⍵∘=¨F←' htc'⋄⎕SM∘←1 1,⍨⊂N←F[1+⊃+/H h(t∨c≠H←c∧S↑1 1↓1 2∊⍨⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂¯1⌽¯1⊖h↑⍨2+S←25 79)ר⍳3]⋄∇N⊣⎕DL÷4}↑{79↑⍞}¨⍳25

A saída é exibida na ⎕SMjanela. A simulação é executada sem fim. A grade é 79x25, porque esse é o tamanho padrão da ⎕SMjanela. A cabeça do elétron é h, a cauda é t, o cobre é c. O programa lê a configuração inicial do teclado como 25 linhas.

Explicação:

  • ↑{79↑⍞}¨⍳25: leia a grade 79x25
  • h t c←1↓⍵∘=¨F←' htc': obtenha três matrizes, uma com as cabeças, uma com as caudas e outra com o cobre. Defina também F como a sequência ' htc'.

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: A parte "..." é um vetor de comprimento três, onde os elementos são matrizes que mostram as novas cabeças, caudas e cobre, respectivamente. As cabeças são multiplicadas por 1, as caudas por 2 e o cobre por 3. Em seguida, somamos essas matrizes e adicionamos uma, fornecendo uma matriz de índices F. Nse torna o novo estado, no mesmo formato da entrada, e é mostrado na ⎕SMtela, começando no canto superior esquerdo.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Adicione uma borda de espaços em branco haumentando-a em duas linhas e colunas e girando-a uma para a direita e outra para baixo.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Gire a matriz nas oito direções e some as matrizes resultantes, fornecendo a quantidade de vizinhos que são cabeças em cada posição.

  • 1 2∊⍨: Defina apenas as posições para 1 com 1 ou 2 vizinhos.

  • S↑1 1↓: Remova a borda que adicionamos anteriormente.

  • H←c∧: As novas cabeças são todas as células de cobre que têm 1 ou 2 vizinhos de cabeça.

  • t∨c≠H: As novas células de cobre são todas caudas antigas e todas as células de cobre antigas que não se tornaram cabeças.

  • H h(... ): As novas cabeças são Hcomo calculadas acima, as novas caudas são as cabeças antigas e as novas células de cobre são calculadas acima.

  • ∇N⊣⎕DL÷4: Aguarde 1/4 de segundo e execute a função novamente N.

marinus
fonte
Eu acho que seria melhor se pudesse conter uma grade de 40 por 40.
mbomb007
6

ALPACA, 82 caracteres

ALPACA é uma linguagem projetada especificamente para autômatos celulares.

o não é nada; c é condutor; e é elétron; t é cauda eletrônica.

state o " ";
state c "c" to e when 1 e or 2 e;
state e "e" to t;
state t "t" to c.
DanTheMan
fonte
Quando esse idioma foi lançado? Existem links para o idioma?
Optimizer
@Optimizer Aqui está você! Eu não fiz o idioma.
DanTheMan
4
Legal. Linguagem certa para o desafio certo ..
Optimizer
4

GolfScript ( 125 120 105 100 caracteres)

n%{.,,{1${.0=,:w[1,*]\+2*>3<}:^~`{zip^''+.4=5%'`X '@{+}*(7&1>'iX'>+=}+w,%}%"\033[H\033[J"@n*+puts 6.?.?}do

Observe que estou contando o \033caractere como um cada, porque eles podem ser substituídos por um ESCcaractere literal . Isso usa códigos de controle ANSI, portanto, depende de um tty compatível. Observe também que os quadros são impressos começando com a grade de entrada.

Há alguma sobreposição com Gerar uma grade de somas , que também usa o bairro de Moore.

Codificação: espaço em branco => ; cabeça de elétrons => i; cauda eletrônica => `; cobre => X.

A pausa entre as iterações é o tempo necessário para calcular 46656 46656 . Mudar 6.?.?para outra expressão permite controlar a velocidade; o próximo mais lento para a mesma contagem de caracteres é 7.?.?, que é muito mais lento (a saída é 22 vezes maior e não é um cálculo de complexidade linear).

Para um caso de teste, eu tenho usado

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

do desafio Rosetta Code Wireworld .

Peter Taylor
fonte
3

Python 371 341 caracteres

Sim, não é tão curto, mas tem uma interface interativa!

import matplotlib.pylab as l,scipy.ndimage as i
r=round
w=l.zeros((40,40),int)-1
p=l.matshow(w,vmax=2)
c=p.figure.canvas
def h(e):
 try:w[r(e.ydata),r(e.xdata)]=[0,2,-1][e.button-1]
 except:x=i.convolve(w==2,l.ones((3,3)),int,'constant');w[:]=w/2+((w==0)&(x>0)&(x<3))*2
 p.set_data(w);c.draw()
c.mpl_connect('button_press_event',h)
l.show()

Instruções:

Clique com o botão esquerdo do mouse para colocar o fio

Clique com o botão direito do mouse para limpar

Clique com o botão do meio do mouse para colocar a cabeça do elétron

Clique fora dos eixos para pisar no autômato

Geoff Reedy
fonte
(x>0)&(x<3)-> (0<x<3). :)
beary605
3

Python ( 243 214)

Tentou fazer um cruzamento entre usabilidade e personagens. A grade é 40x40. A entrada é fornecida no stdin. Uma cabeça de elétrons é h, uma cauda de elétrons t, um cobre c, qualquer outra coisa está em branco.

import os
f=raw_input()
while 1:f=''.join('h'if(i=='c')&(0<sum(1 for i in[-1,1,-39,-40,-41,39,40,41]if f[e+i:e+i+1]=='h')<3)else't'if i=='h'else'c'if i=='t'else f[e]for e,i in enumerate(f));os.system('cls');print f

O loop while (linha 3) não compactado (não funcionará se inserido no código):

while 1:
 for e,i in enumerate(f):
  if(i=='c')&(0<sum(1 for i in[-1,1,-39,-40,-41,39,40,41]if f[e+i:e+i+1]=='h')<3):f[e]='h'
  elif i=='h':f[e]='t'
  elif i=='t':f[e]='c'
  else:f[e]=f[e]  #redundant, but Python needs this to run
 os.system('cls') #cls is shorter than clear, so I used that
 print f
beary605
fonte
Eu acho que você pode substituir linhas 5-7 com uma única expressão: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. Não tenho certeza se isso funciona exatamente como é, mas algo nesse sentido deve funcionar
strigoides
2

C, 355 347 300 294 caracteres

Edit: percebi que não preciso feof()

Editar: salvou 47 caracteres! Removeu o sono, se livrou de quase todos os aparelhos, combinou muitas operações.

Edit: Último hoje, desde que eu quebrei 300 caracteres. Mudou printfpara puts, encontrou uma otimização bonitinha com a primeira comparação.

C não se presta bem a esse tipo de problema, mas ei, jogar golfe é divertido. Essa é uma implementação de força bruta, mas eu queria ver até onde eu poderia melhorar.

Entrada é um arquivo de texto chamado i. Ele contém uma representação do estado inicial, com espaço *para cobre, +para cabeça -de elétrons, cauda de elétrons, espaços para células vazias. Estou usando o portão XOR da página wiki para teste.

   ****-+**
  +        ******
   -*******      *
                ****
                *  *****
                ****
   ********      *
  +        ******
   -****+-*

char*p,t[42][42],s[42][42];
main(i,r,c,n,j)
{
  for(p=fopen("i","r");fgets(s[i++]+1,40,p););

  for(;;getch(),memcpy(s,t,1764))
    for(j=1;j<41;puts(s[j++]+1))
      for(i=1;i<41;)
      {
        p=t[j]+i;
        r=s[j][i++];
        *p=r==43?45:r;
        if(r==45)
          *p=42;
        if(r==42)
          for(r=-1,n=0;r<2;++r,*p=n&&n<3?43:42)
            for(c=-2;c<1;)
              n+=s[j+r][i+c++]==43;
      }
}
JoeFish
fonte
Poderia cond?43:42ser escrito 42+(cond)? E tenho certeza que r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;pode ser reduzido para r=s[j][i++];*p=r==43?45:r==45?42:r;se nãor=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor
1

Python, 234 218 caracteres

import time
I=input
C=I()
H=I()
T=I()
R=range(40)
while 1:
 for y in R:print''.join(' CHT'[(C+H+2*T).count(x+y*1j)]for x in R)
 H,T=[c for c in C if 0<sum(1 for h in H if abs(c-h)<2)<3and c not in H+T],H;time.sleep(.1)

Você insere o quadro como três listas de números complexos que representam as coordenadas das células de cobre (que devem incluir as listas de cara e coroa), cara e coroa. Aqui está um exemplo:

[3+2j+x for x in range(8)] + [3+4j+x for x in range(8)] + [11+3j+x for x in range(6)] + [2+3j]
[3+2j]
[2+3j]

Observe que temos evala entrada, para que você possa usar expressões arbitrariamente complexas para listas de números complexos.

Keith Randall
fonte
1

QBasic, 309 bytes

Aviso: a versão golfed não é fácil de usar: possui um método de entrada estranho, é executado como um loop infinito e não possui nenhum atraso (portanto, é executado muito rápido em alguns sistemas). Somente execute-o se você souber finalizar um programa no seu ambiente QBasic. A versão ungolfed é recomendada (veja abaixo).

INPUT w,h
SCREEN 9
FOR y=1TO h
FOR x=1TO w
PSET(x,y),VAL(INPUT$(1))
NEXT
NEXT
DO
FOR y=1TO h
FOR x=1TO w
SCREEN,,0
c=POINT(x,y)
d=c
IF c=7THEN d=1
IF c=1THEN d=6
IF c=6THEN
n=0
FOR v=y-1TO y+1
FOR u=x-1TO x+1
n=n-(POINT(u,v)=7)
NEXT
NEXT
d=7+(n=0OR n>2)
END IF
SCREEN,,1,0
PSET(x,y),d
NEXT
NEXT
PCOPY 1,0
LOOP

Para executar, especifique no prompt de entrada a largura we a altura da sua configuração h. 1 Em seguida, digite w*hos códigos de um dígito para as células (movendo-se da esquerda para a direita e depois de cima para baixo), com

  • 0 = vazio
  • 6 = fio
  • 7 = cabeça de sinal
  • 1 = cauda do sinal

Depois de inserir todas as células, a simulação começará (e continuará para sempre, até você finalizar o programa).

Ungolfed

Uma versão mais amigável. Para modificar o layout, modifique oDATA instruções no final.

O código tira proveito da POINTfunção, que lê o valor da cor de um pixel na tela. Isso significa que não precisamos armazenar as células separadamente como uma matriz. Para garantir que todas as células sejam atualizadas simultaneamente, realizamos as atualizações em uma segunda "página". Podemos alternar a página ativa usando uma versão da SCREENdeclaração e copiar o conteúdo de uma página para outra usando a PCOPYdeclaração.

SCREEN 9

EMPTY = 0 ' Black
HEAD = 7  ' Light gray
TAIL = 1  ' Blue
WIRE = 6  ' Brown/orange

' First two data values are the width and height
READ w, h
' The rest are the initial configuration, row by row
' Read them and plot the appropriately colored pixels
FOR y = 1 TO h
  FOR x = 1 TO w
    READ state$
    IF state$ = "" THEN value = EMPTY
    IF state$ = "H" THEN value = HEAD
    IF state$ = "T" THEN value = TAIL
    IF state$ = "W" THEN value = WIRE
    PSET (x, y), value
  NEXT x
NEXT y

' Loop the simulation until user presses a key
DO UNTIL INKEY$ <> ""
  ' Store current time for delay purposes
  t# = TIMER

  FOR y = 1 TO h
    FOR x = 1 TO w
      ' Active page = display page = 0
      SCREEN , , 0
      ' Get the color value of the pixel at x,y
      oldVal = POINT(x, y)
      IF oldVal = EMPTY THEN
        newVal = EMPTY
      ELSEIF oldVal = HEAD THEN
        newVal = TAIL
      ELSEIF oldVal = TAIL THEN
        newVal = WIRE
      ELSEIF oldVal = WIRE THEN
        neighbors = 0
        FOR ny = y - 1 TO y + 1
          FOR nx = x - 1 TO x + 1
            IF POINT(nx, ny) = HEAD THEN neighbors = neighbors + 1
          NEXT nx
        NEXT ny
        IF neighbors = 1 OR neighbors = 2 THEN
          newVal = HEAD
        ELSE
          newVal = WIRE
        END IF
      END IF
      ' Active page = 1, display page = 0
      SCREEN , , 1, 0
      ' Plot the new value on page 1
      PSET (x, y), newVal
    NEXT x
  NEXT y

  ' Copy page 1 to page 0
  PCOPY 1, 0

  ' Delay
  WHILE TIMER >= t# AND t# + 0.2 > TIMER
  WEND
LOOP

DATA 8,5
DATA T,H,W,W,W,W,W,W
DATA W, , , ,W, , , 
DATA  , , ,W,W,W, , 
DATA W, , , ,W, , , 
DATA H,T,W,W, ,W,W,W

1 Os valores máximos de largura e altura dependem de qual modo de tela é usado. EmSCREEN 9 , a largura pode ser de até 638 e a altura de 348. SCREEN 7possui uma resolução menor (tamanho máximo de configuração 318 por 198), mas os pixels são maiores e, portanto, mais fáceis de ver (no DOS QBasic ou no emulador DOSBox - infelizmente, o QB64 apenas abre uma janela menor).

Exemplo de execução

Versão não destruída em archive.org , com modo de tela 7:

Wireworld em QBasic

DLosc
fonte