Simule el autómata celular Wireworld

24

Wireworld es un autómata celular diseñado para parecerse a los electrones que fluyen a través de los cables. Su mecánica simple permite la construcción de circuitos digitales. Incluso ha permitido la construcción de una computadora completa .

Su misión es crear la implementación más corta de Wireworld en el idioma que elija.

Cada celda de la cuadrícula tiene uno de cuatro estados. Los cuatro estados son "en blanco", "cobre", "cabeza de electrones" o "cola de electrones".

  • Una celda en blanco siempre seguirá siendo una celda en blanco
  • Una cabeza de electrones siempre se convertirá en una cola de electrones.
  • Una cola de electrones siempre se convertirá en cobre
  • Una celda de cobre se convertirá en una cabeza de electrones si exactamente uno o dos de sus ocho vecinos son cabezas de electrones, de lo contrario seguirá siendo cobre

Esta competencia tendrá un estilo similar a la competencia Juego más corto de la vida , pero con algunos cambios.

  • La cuadrícula debe tener al menos 40 por 40 celdas
  • Los bordes de la cuadrícula NO deben envolverse (no un toro). Trate las células fuera del campo como si estuvieran constantemente "en blanco".
  • Los usuarios deben poder ingresar su propia configuración inicial.
  • Mirar fijamente las pantallas en blanco no es divertido. El programa debe mostrar visualmente la simulación mientras se ejecuta.

Este es el código de golf, menos bytes gana.

PhiNotPi
fuente

Respuestas:

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

La salida se muestra en la ⎕SMventana. La simulación se ejecuta sin cesar. La cuadrícula es 79x25 porque ese es el tamaño predeterminado de la ⎕SMventana. La cabeza del electrón es h, la cola es t, el cobre es c. El programa lee la configuración inicial desde el teclado como 25 líneas.

Explicación:

  • ↑{79↑⍞}¨⍳25: lea la cuadrícula de 79x25
  • h t c←1↓⍵∘=¨F←' htc': obtenga tres matrices, una con las cabezas, una con las colas y otra con el cobre. También establezca F en la cadena ' htc'.

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: La parte "..." es un vector de longitud tres, donde los elementos son matrices que muestran las nuevas cabezas, colas y cobre, respectivamente. Las cabezas se multiplican por 1, las colas por 2 y el cobre por 3, luego sumamos estas matrices y sumamos una, dando una matriz de índices F. Nse convierte en el nuevo estado, en el mismo formato que la entrada, y se muestra en la ⎕SMpantalla desde la esquina superior izquierda.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Agregue un borde de espacios en blanco creciéndolo en hdos filas y columnas, luego gírelo uno hacia la derecha y otro hacia abajo.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Gire la matriz en las ocho direcciones y luego sume las matrices resultantes, dando la cantidad de vecinos que son cabezas en cada posición.

  • 1 2∊⍨: Establezca solo aquellas posiciones en 1 que tengan 1 o 2 vecinos.

  • S↑1 1↓: Elimine el borde que agregamos anteriormente.

  • H←c∧: Las nuevas cabezas son todas esas celdas de cobre que tienen 1 o 2 cabezas vecinas.

  • t∨c≠H: Las nuevas celdas de cobre son todas colas viejas, y todas las celdas de cobre viejas que no se han convertido en cabezas.

  • H h(... ): Las nuevas cabezas son Hcomo se calculó anteriormente, las nuevas colas son las viejas cabezas, y las nuevas celdas de cobre son como se calculó anteriormente.

  • ∇N⊣⎕DL÷4: Espere 1/4 de segundo, luego vuelva a ejecutar la función N.

marinus
fuente
Creo que sería mejor si pudiera contener una cuadrícula de 40 por 40.
mbomb007
6

ALPACA, 82 caracteres

ALPACA es un lenguaje diseñado específicamente para autómatas celulares.

o no es nada; c es conductor; e es electrón; t es cola de electrones.

state o " ";
state c "c" to e when 1 e or 2 e;
state e "e" to t;
state t "t" to c.
DanTheMan
fuente
¿Cuándo se lanzó este lenguaje? ¿Hay algún enlace para el idioma?
Optimizador
@Optimizer ¡ Aquí tienes! No hice el idioma.
DanTheMan
44
Guay. Lenguaje correcto para el desafío correcto ..
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

Tenga en cuenta que cuento \033como un carácter cada uno, porque pueden reemplazarse por un ESCcarácter literal . Esto utiliza códigos de control ANSI, por lo que se basa en un tty compatible. También tenga en cuenta que los marcos se imprimen comenzando con la cuadrícula de entrada.

Existe cierta superposición con Generar una cuadrícula de sumas , que también utiliza el vecindario de Moore.

Codificación: espacio en blanco => ; cabeza de electrones => i; cola de electrones => `; cobre => X.

La pausa entre iteraciones es el tiempo requerido para calcular 46656 46656 . Cambiar 6.?.?a otra expresión le permite controlar la velocidad; la siguiente más lenta para el mismo recuento de caracteres es 7.?.?, que es mucho más lenta (la salida es 22 veces mayor y no es un cálculo de complejidad lineal).

Para un caso de prueba, he estado usando

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

del desafío Rosetta Code Wireworld .

Peter Taylor
fuente
3

Python 371 341 caracteres

Sí, no es tan corto, ¡pero tiene una interfaz gráfica de usuario interactiva!

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

Instrucciones:

Haga clic con el botón izquierdo del mouse para colocar el cable

Haga clic con el botón derecho del mouse para borrar

Haga clic con el botón central del mouse para colocar la cabeza del electrón

Haga clic fuera de los ejes para pisar el autómata.

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

Pitón ( 243 214)

Intenté hacer un cruce entre usabilidad y personajes. La cuadrícula es 40x40. La entrada se da en stdin. Una cabeza de electrones es h, la cola de electrones es t, el cobre es c, cualquier otra cosa está en blanco.

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

El ciclo while (línea 3) sin comprimir (no funcionará si se coloca en el 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
fuente
Creo que se puede reemplazar las líneas de 5-7 con una sola expresión: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. No estoy seguro si eso funciona exactamente como es, pero algo en ese sentido debería funcionar
Strigoides
2

C, 355 347 300 294 caracteres

Editar: me di cuenta de que no necesito feof()

Editar: Guardado 47 caracteres! Eliminó el sueño, eliminó casi todos los aparatos ortopédicos, combinó muchas operaciones.

Editar: El último hoy, desde que rompí 300 caracteres. Cambió printfa puts, encontró una pequeña optimización linda con la primera comparación.

C no se presta bien a este tipo de problema, pero bueno, jugar al golf es divertido. Esta es una implementación de fuerza bruta bastante, pero quería ver hasta dónde podía jugar golf.

La entrada es un archivo de texto llamado i. Contiene una representación del estado inicial, con *para cobre, +para cabeza de electrón, -para cola de electrón, espacios para celdas vacías. Estoy usando la puerta XOR de la página wiki para realizar pruebas.

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

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
fuente
Podría cond?43:42ser escrito 42+(cond)? Y estoy seguro de que r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;puede reducirse r=s[j][i++];*p=r==43?45:r==45?42:r;si no es asír=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)

Ingrese el tablero como tres listas de números complejos que representan las coordenadas de las celdas de cobre (que deben incluir las listas de cabezas y colas), caras y colas. Aquí hay un ejemplo:

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

Tenga en cuenta que nosotros eval la entrada, por lo que puede usar expresiones complejas arbitrariamente para listas de números complejos.

Keith Randall
fuente
1

QBasic, 309 bytes

Advertencia: la versión de golf no es fácil de usar: tiene un método de entrada extraño, funciona como un bucle infinito y no tiene ningún retraso (por lo tanto, se ejecuta demasiado rápido en algunos sistemas). Solo ejecútelo si sabe cómo terminar un programa en su entorno QBasic. Se recomienda la versión sin golf (ver más abajo).

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 ejecutar, especifique en el indicador de entrada el ancho wy alto de su configuración h. 1 Luego escriba w*hcódigos de un solo dígito para las celdas (moviéndose de izquierda a derecha, luego de arriba a abajo), con

  • 0 = vacío
  • 6 = cable
  • 7 = cabeza de señal
  • 1 = cola de señal

Una vez que haya ingresado todas las celdas, comenzará la simulación (y continuará para siempre, hasta que elimine el programa).

Sin golf

Una versión más fácil de usar. Para modificar el diseño, modifique las DATAdeclaraciones al final.

El código aprovecha la POINTfunción, que lee el valor de color de un píxel de la pantalla. Esto significa que no tenemos que almacenar las celdas por separado como una matriz. Para asegurarnos de que todas las celdas se actualicen simultáneamente, realizamos las actualizaciones en una segunda "página". Podemos alternar la página activa usando una versión de la SCREENdeclaración, y copiar el contenido de una página a otra usando la PCOPYdeclaración.

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 Los valores máximos para ancho y alto dependen del modo de pantalla utilizado. En SCREEN 9, el ancho puede ser de hasta 638 y la altura de hasta 348.SCREEN 7 tiene una resolución más pequeña (tamaño de configuración máximo de 318 por 198), pero los píxeles son más grandes y, por lo tanto, más fáciles de ver (en DOS QBasic o el emulador DOSBox, desafortunadamente QB64 solo da una ventana más pequeña).

Ejecución de ejemplo

Versión sin golf en archive.org , con modo de pantalla 7:

Wireworld en QBasic

DLosc
fuente