Symuluj automat komórkowy Wireworld

24

Wireworld to automat komórkowy, który został zaprojektowany tak, aby przypominać elektrony przepływające przez przewody. Jego prosta mechanika pozwala na budowę obwodów cyfrowych. Pozwoliło to nawet na budowę całego komputera .

Twoim zadaniem jest stworzenie najkrótszej implementacji Wireworld w wybranym języku.

Każda komórka w siatce ma jeden z czterech stanów. Cztery stany to „pusty”, „miedź”, „głowa elektronu” lub „ogon elektronu”.

  • Pusta komórka zawsze pozostanie pustą komórką
  • Głowa elektronowa zawsze będzie ogonem elektronowym
  • Ogon elektronowy zawsze będzie miedziany
  • Ogniwo miedzi stanie się głowicą elektronów, a dokładnie jeden lub dwa z ośmiu sąsiadów to głowy elektronów, w przeciwnym razie pozostanie miedzią

Ten konkurs będzie miał podobny styl jak konkurs Najkrótszej gry życia , ale z kilkoma zmianami.

  • Siatka musi mieć co najmniej 40 na 40 komórek
  • Krawędzie siatki NIE mogą się owijać (nie torus). Traktuj komórki poza polem jako stale „puste”.
  • Użytkownicy muszą mieć możliwość wprowadzenia własnej konfiguracji początkowej.
  • Patrzenie na puste ekrany nie jest zabawne. Program musi wyświetlać symulację w trakcie działania.

To jest kod golfowy, najmniej bajtów wygrywa.

PhiNotPi
źródło

Odpowiedzi:

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

Dane wyjściowe są wyświetlane w ⎕SMoknie. Symulacja przebiega bez końca. Siatka ma wymiary 79 x 25, ponieważ jest to domyślny rozmiar ⎕SMokna. Głowica elektronowa jest h, ogon jest t, miedź jest c. Program odczytuje konfigurację początkową z klawiatury jako 25 wierszy.

Wyjaśnienie:

  • ↑{79↑⍞}¨⍳25: przeczytaj siatkę 79x25
  • h t c←1↓⍵∘=¨F←' htc': zdobądź trzy matryce, jedną z głowami, jedną z ogonami i jedną z miedzią. Ustaw także F na ciąg ' htc'.

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: Część „...” jest wektorem o długości trzy, gdzie elementy są matrycami pokazującymi odpowiednio nowe główki, ogony i miedź. Głowice są mnożone przez 1, ogony przez 2, a miedź przez 3, następnie sumujemy te macierze razem i dodajemy jedną, dając macierz indeksów F. Nstaje się nowym stanem, w tym samym formacie co dane wejściowe, i jest pokazywany na ⎕SMekranie, zaczynając od lewego górnego rogu.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Dodaj granicę odstępów h, powiększając ją o dwa rzędy i kolumny, a następnie obracając o jedną w prawo i jedną w dół.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Obróć matrycę we wszystkich ośmiu kierunkach, a następnie zsumuj otrzymane macierze razem, podając liczbę sąsiadów, którzy są głowami w każdej pozycji.

  • 1 2∊⍨: Ustaw tylko te pozycje na 1, które mają 1 lub 2 sąsiadów.

  • S↑1 1↓: Usuń obramowanie, które dodaliśmy wcześniej.

  • H←c∧: Nowe głowy to wszystkie te miedziane komórki, które mają 1 lub 2 głównych sąsiadów.

  • t∨c≠H: Wszystkie nowe ogniwa miedziane to wszystkie stare ogony i wszystkie stare ogniwa miedziane, które nie stały się głowami.

  • H h(... ): Nowe głowice są Hjak obliczono powyżej, nowe ogony są starymi głowami, a nowe ogniwa miedziane są jak obliczono powyżej.

  • ∇N⊣⎕DL÷4: Poczekaj 1/4 sekundy, a następnie uruchom ponownie funkcję N.

marinus
źródło
Myślę, że byłoby lepiej, gdyby mógł zawierać siatkę 40 na 40.
mbomb007
6

ALPACA, 82 znaki

ALPACA to język specjalnie zaprojektowany dla automatów komórkowych.

o jest niczym; c jest przewodnikiem; e oznacza elektron; t jest ogonem elektronowym.

state o " ";
state c "c" to e when 1 e or 2 e;
state e "e" to t;
state t "t" to c.
DanTheMan
źródło
Kiedy został wydany ten język? Czy są jakieś linki do tego języka?
Optymalizator
@Optimizer Proszę bardzo! Nie stworzyłem języka.
DanTheMan
4
Fajne. Właściwy język dla właściwego wyzwania.
Optymalizator
4

GolfScript ( 125 120 105 100 znaków)

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

Zauważ, że liczę \033jako jeden znak, ponieważ można je zastąpić dosłownie ESC. Używa kodów kontrolnych ANSI, więc polega na kompatybilnym tty. Należy również pamiętać, że ramki są drukowane począwszy od siatki wejściowej.

W pewnym stopniu nakłada się na Generuj siatkę sum , która również wykorzystuje sąsiedztwo Moore.

Kodowanie: puste miejsce => ; głowa elektronu => i; ogon elektronowy => `; miedź => X.

Przerwa między iteracjami to czas wymagany do obliczenia 46656 46656 . Zmiana 6.?.?na inne wyrażenie pozwala kontrolować prędkość; następny najwolniejszy dla tej samej liczby znaków jest 7.?.?, który jest znacznie wolniejszy (wynik jest 22 razy większy i nie jest to obliczenie liniowej złożoności).

Do testu użyłem

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

z konkursu Rosewta Code Wireworld .

Peter Taylor
źródło
3

Znaki Python 371 341

Tak, nie jest tak krótki, ale ma interaktywne GUI!

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

Instrukcje:

Kliknij lewym przyciskiem myszy, aby umieścić drut

Kliknij prawym przyciskiem myszy, aby wyczyścić

Kliknij środkowym przyciskiem myszy, aby umieścić głowicę elektronową

Kliknij poza osiami, aby przejść do automatu

Geoff Reedy
źródło
(x>0)&(x<3)-> (0<x<3). :)
beary605
3

Python ( 243 214)

Próbowałem stworzyć skrzyżowanie użyteczności z postaciami. Siatka ma wymiary 40 x 40. Dane wejściowe podano na stdin. Głowica elektronowa jest h, ogon elektronowy t, miedź jest c, wszystko inne jest puste.

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

Pętla while (linia 3) nieskompresowana (nie będzie działać, jeśli zostanie umieszczona w kodzie):

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
źródło
Myślę, że można zastąpić linie 5-7 z jednym wyrażeniem: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. Nie jestem pewien, czy to działa dokładnie tak, jak jest, ale coś w tym stylu powinno działać
Strigoides,
2

C, 355 347 300 294 znaków

Edycja: zdałem sobie sprawę, że nie potrzebuję feof()

Edycja: Zapisano 47 znaków! Usunąłem Sen, pozbyłem się prawie wszystkich aparatów ortodontycznych, połączyłem wiele operacji.

Edytuj: Ostatni dzisiaj, odkąd złamałem 300 znaków. Zmieniono printfna puts, znalazłem uroczą małą optymalizację przy pierwszym porównaniu.

C nie nadaje się dobrze do tego rodzaju problemów, ale hej, gra w golfa jest fajna. Jest to dość brutalna implementacja, ale chciałem zobaczyć, jak daleko mogę grać w golfa.

Dane wejściowe to plik tekstowy o nazwie i. Zawiera przedstawienie stanu początkowego, *dla miedzi, +dla głowy elektronowej, -dla ogona elektronowego, przestrzeni dla pustych komórek. Do testowania używam bramki XOR ze strony wiki.

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

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
źródło
Mógłby cond?43:42być napisany 42+(cond)? I jestem pewien, że r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;można zredukować do, r=s[j][i++];*p=r==43?45:r==45?42:r;jeśli nie dor=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor
1

Python, 234 218 znaków

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)

Wpisujesz tablicę jako trzy listy liczb zespolonych reprezentujących współrzędne komórek miedzi (które muszą zawierać listy głów i ogonów), głów i ogonów. Oto przykład:

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

Zauważ, że mamy evaldane wejściowe, dzięki czemu możesz używać dowolnie złożonych wyrażeń do list liczb zespolonych.

Keith Randall
źródło
1

QBasic, 309 bajtów

Ostrzeżenie: wersja gry w golfa nie jest przyjazna dla użytkownika: ma dziwną metodę wprowadzania, działa jako nieskończona pętla i nie ma żadnych opóźnień (dlatego działa zbyt szybko w niektórych systemach). Uruchom go tylko, jeśli wiesz, jak zakończyć program w środowisku QBasic. Zalecana jest wersja bez golfa (patrz poniżej).

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

Aby uruchomić, w wierszu poleceń podaj szerokość wi wysokość konfiguracji h. 1 Następnie wpisz w*hjednocyfrowe kody komórek (od lewej do prawej, a następnie od góry do dołu), za pomocą

  • 0 = pusty
  • 6 = drut
  • 7 = głowica sygnalizacyjna
  • 1 = ogon sygnałowy

Po wprowadzeniu wszystkich komórek rozpocznie się symulacja (i będzie trwała wiecznie, aż do momentu zabicia programu).

Bez golfa

Bardziej przyjazna dla użytkownika wersja. Aby zmodyfikować układ, zmodyfikuj DATAinstrukcje na końcu.

Kod wykorzystuje POINTfunkcję, która odczytuje wartość koloru piksela z ekranu. Oznacza to, że nie musimy przechowywać komórek osobno jako tablicy. Aby upewnić się, że wszystkie komórki aktualizują się jednocześnie, wykonujemy aktualizacje na drugiej „stronie”. Możemy przełączać aktywną stronę za pomocą wersji SCREENinstrukcji i kopiować zawartość jednej strony na drugą za pomocą PCOPYinstrukcji.

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 Maksymalne wartości szerokości i wysokości zależą od używanego trybu ekranu. W SCREEN 9, szerokość może wynosić do 638, a wysokość do 348. SCREEN 7ma mniejszą rozdzielczość (maksymalny rozmiar konfiguracji 318 na 198), ale piksele są większe i dlatego łatwiej je zobaczyć (na DOS QBasic lub emulatorze DOSBox - niestety QB64 tylko daje mniejsze okno).

Przykładowy przebieg

Wersja bez golfa na archive.org , z trybem ekranu 7:

Wireworld w QBasic

DLosc
źródło