Simula l'automa cellulare Wireworld


24

Wireworld è un automa cellulare progettato per assomigliare agli elettroni che fluiscono attraverso i fili. La sua meccanica semplice consente la costruzione di circuiti digitali. Ha persino permesso la costruzione di un intero computer .

La tua missione è quella di creare l'implementazione Wireworld più breve nella tua lingua preferita.

Ogni cella nella griglia ha uno su quattro stati. I quattro stati sono "vuoti", "rame", "testa dell'elettrone" o "coda dell'elettrone".

  • Una cella vuota rimarrà sempre una cella vuota
  • Una testa di elettroni diventerà sempre una coda di elettroni
  • Una coda di elettroni diventerà sempre rame
  • Una cella di rame diventerà una testa di elettrone se esattamente uno o due dei suoi otto vicini sono teste di elettroni, altrimenti rimarrà di rame

Questa competizione avrà uno stile simile a quella del gioco più corto della vita , ma con alcune modifiche.

  • La griglia deve essere almeno 40 per 40 celle
  • I bordi della griglia NON devono avvolgersi (non un toro). Tratta le cellule fuori dal campo come costantemente "vuote".
  • Deve essere possibile per gli utenti inserire la propria configurazione iniziale.
  • Fissare schermi vuoti non è divertente. Il programma deve visualizzare visivamente la simulazione mentre è in esecuzione.

Questo è il golf del codice, vince meno byte.

Risposte:


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

L'output viene visualizzato nella ⎕SMfinestra. La simulazione funziona all'infinito. La griglia è 79x25 perché è la dimensione predefinita della ⎕SMfinestra. La testa dell'elettrone è h, la coda è t, il rame è c. Il programma legge la configurazione iniziale dalla tastiera come 25 righe.

Spiegazione:

  • ↑{79↑⍞}¨⍳25: leggi la griglia 79x25
  • h t c←1↓⍵∘=¨F←' htc': ottieni tre matrici, una con la testa, una con la coda e una con il rame. Impostare anche F sulla stringa ' htc'.

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: La parte "..." è un vettore di lunghezza tre, in cui gli elementi sono matrici che mostrano rispettivamente le nuove teste, code e rame. Le teste vengono moltiplicate per 1, le code per 2 e il rame per 3, quindi sommiamo queste matrici insieme e ne aggiungiamo una, dando una matrice di indici in F. Ndiventa il nuovo stato, nello stesso formato dell'input, e viene mostrato sullo ⎕SMschermo a partire dall'angolo in alto a sinistra.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Aggiungi un bordo di spazi vuoti hfacendolo crescere di due righe e colonne, quindi ruotandolo di uno a destra e uno in basso.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Ruota la matrice in tutte e otto le direzioni e quindi somma le matrici risultanti insieme, fornendo la quantità di vicini che sono a capo in ogni posizione.

  • 1 2∊⍨: Imposta solo quelle posizioni su 1 che hanno 1 o 2 vicini.

  • S↑1 1↓: Rimuovi il bordo che abbiamo aggiunto in precedenza.

  • H←c∧: Le nuove teste sono tutte quelle celle di rame che hanno 1 o 2 vicini di testa.

  • t∨c≠H: Le nuove celle di rame sono tutte vecchie code e tutte le vecchie celle di rame che non sono diventate teste.

  • H h(... ): Le nuove teste sono Hcome sopra calcolate, le nuove code sono le vecchie teste e le nuove celle di rame sono come sopra calcolate.

  • ∇N⊣⎕DL÷4: Attendere 1/4 di secondo, quindi riavviare la funzione N.


Penso che sarebbe meglio se potesse contenere una griglia 40 per 40.
mbomb007,

6

ALPACA, 82 caratteri

ALPACA è un linguaggio appositamente progettato per gli automi cellulari.

o è niente; c è conduttore; e è elettrone; t è coda di elettroni.

state o " ";
state c "c" to e when 1 e or 2 e;
state e "e" to t;
state t "t" to c.

Quando è stata rilasciata questa lingua? Ci sono collegamenti per la lingua?
Ottimizzatore

@Optimizer Ecco qua! Non ho fatto la lingua.
DanTheMan,

4
Freddo. La lingua giusta per la sfida giusta ..
Ottimizzatore

4

GolfScript ( 125 120 105 100 caratteri)

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

Nota che sto contando \033ciascuno come un personaggio, perché possono essere sostituiti da un ESCcarattere letterale . Questo utilizza codici di controllo ANSI, quindi si basa su un tty compatibile. Si noti inoltre che i frame vengono stampati a partire dalla griglia di input.

C'è una certa sovrapposizione con Genera una griglia di somme , che utilizza anche il quartiere di Moore.

Codifica: spazio vuoto => ; testa dell'elettrone => i; coda dell'elettrone => `; rame => X.

La pausa tra le iterazioni è il tempo necessario per calcolare 46656 46656 . Il passaggio 6.?.?a un'altra espressione consente di controllare la velocità; il successivo più lento per lo stesso numero di caratteri è 7.?.?, che è molto più lento (l'output è 22 volte più grande e non è un calcolo di complessità lineare).

Per un caso di test, ho usato

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

dalla sfida Wireworld di Rosetta Code .


3

Python 371 341 caratteri

Sì, non è così breve, ma ha una GUI interattiva!

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

Istruzioni:

Fare clic con il tasto sinistro del mouse per posizionare il filo

Fare clic con il tasto destro del mouse per cancellare

Fare clic con il pulsante centrale del mouse per posizionare la testa dell'elettrone

Fare clic all'esterno degli assi per far avanzare l'automa


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

3

Python ( 243 214)

Ho cercato di creare un incrocio tra usabilità e personaggi. La griglia è 40x40. L'input è dato su stdin. Una testa di elettrone è h, la coda di un elettrone è t, il rame è c, qualsiasi altra cosa è vuota.

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

Il ciclo while (riga 3) non compresso (non funzionerà se inserito nel codice):

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

Penso che si possa sostituire le righe 5-7 con una sola espressione: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. Non sono sicuro che funzioni esattamente così, ma qualcosa del genere dovrebbe funzionare
Strigoides

2

C, 355 347 300 294 caratteri

Modifica: realizzato che non ho bisogno feof()

Modifica: Hai salvato 47 caratteri! Rimosso il sonno, eliminato quasi tutte le parentesi graffe, combinato molte operazioni.

Modifica: l'ultimo oggi, da quando ho rotto 300 caratteri. Modificato printfin puts, ho trovato una piccola ottimizzazione carina con il primo confronto.

C non si presta bene a questo tipo di problema, ma ehi, giocare a golf è divertente. Questa è un'implementazione piuttosto bruta, ma volevo vedere fino a che punto potevo giocare a golf.

L'input è un file di testo chiamato i. Contiene una rappresentazione dello stato iniziale, con *per rame, +per testa elettronica, -per coda elettronica, spazi per celle vuote. Sto usando il gate XOR dalla pagina wiki per i test.

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

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;
      }
}

Potrebbe cond?43:42essere scritto 42+(cond)? E sono sicuro che r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;può essere ridotto a r=s[j][i++];*p=r==43?45:r==45?42:r;se non ar=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor,

1

Python, 234 218 caratteri

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)

Inserisci la scheda come tre elenchi di numeri complessi che rappresentano le coordinate delle celle di rame (che devono includere gli elenchi di teste e code), teste e code. Ecco un esempio:

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

Si noti che abbiamo evall'input, quindi è possibile utilizzare espressioni arbitrariamente complesse per elenchi di numeri complessi.


1

QBasic, 309 byte

Attenzione: la versione golfata non è intuitiva: ha uno strano metodo di input, funziona come un ciclo infinito e non ha alcun ritardo (quindi, funziona troppo velocemente su alcuni sistemi). Eseguilo solo se sai come terminare un programma nel tuo ambiente QBasic. Si consiglia la versione non golfata (vedi sotto).

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

Per eseguire, specificare al prompt di input la larghezza we l'altezza della configurazione h. 1 Quindi digitare i w*hcodici a una cifra per le celle (spostandosi da sinistra a destra, quindi dall'alto verso il basso), con

  • 0 = vuoto
  • 6 = filo
  • 7 = testa del segnale
  • 1 = coda del segnale

Dopo aver inserito tutte le celle, la simulazione avrà inizio (e continuerà per sempre, fino a quando non si uccide il programma).

Ungolfed

Una versione più user-friendly. Per modificare il layout, modificare le DATAistruzioni alla fine.

Il codice sfrutta la POINTfunzione, che legge il valore di colore di un pixel dallo schermo. Ciò significa che non è necessario archiviare le celle separatamente come matrice. Per assicurarci che tutte le celle si aggiornino contemporaneamente, eseguiamo gli aggiornamenti su una seconda "pagina". È possibile attivare o disattivare la pagina attiva utilizzando una versione SCREENdell'istruzione e copiare il contenuto di una pagina in un'altra utilizzando l' PCOPYistruzione.

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 I valori massimi per larghezza e altezza dipendono dalla modalità schermo utilizzata. In SCREEN 9, la larghezza può essere fino a 638 e l'altezza fino a 348. SCREEN 7ha una risoluzione più piccola (dimensione massima della configurazione 318 per 198), ma i pixel sono più grandi e quindi più facili da vedere (su DOS QBasic o l'emulatore DOSBox - purtroppo QB64 solo dà una finestra più piccola).

Esempio di esecuzione

Versione non golfata su archive.org , con modalità schermo 7:

Wireworld in QBasic

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.