Simulieren Sie den Mobilfunkautomaten Wireworld


24

Wireworld ist ein zellularer Automat, der so konzipiert wurde, dass er Elektronen ähnelt, die durch Drähte fließen. Seine einfache Mechanik ermöglicht den Aufbau digitaler Schaltungen. Es hat sogar den Bau eines ganzen Computers ermöglicht .

Ihre Mission ist es, die kürzeste Wireworld-Implementierung in der Sprache Ihrer Wahl zu erstellen.

Jede Zelle im Gitter hat einen von vier Zuständen. Die vier Zustände sind "leer", "Kupfer", "Elektronenkopf" oder "Elektronenschwanz".

  • Eine leere Zelle bleibt immer eine leere Zelle
  • Ein Elektronenkopf wird immer zu einem Elektronenschwanz
  • Ein Elektronenschwanz wird immer zu Kupfer
  • Eine Kupferzelle wird zum Elektronenkopf, wenn genau ein oder zwei ihrer acht Nachbarn Elektronenköpfe sind, andernfalls bleibt sie Kupfer

Dieser Wettbewerb wird einen ähnlichen Stil haben wie der Wettbewerb " Das kürzeste Spiel des Lebens" , jedoch mit ein paar Änderungen.

  • Das Gitter muss mindestens 40 mal 40 Zellen groß sein
  • Die Kanten des Gitters dürfen NICHT umlaufen (kein Torus). Behandle Zellen außerhalb des Feldes als konstant "leer".
  • Die Benutzer müssen in der Lage sein, ihre eigene Startkonfiguration einzugeben.
  • Auf leere Bildschirme zu starren, macht keinen Spaß. Das Programm muss die laufende Simulation visuell anzeigen.

Das ist Codegolf, die wenigsten Bytes gewinnen.

Antworten:


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

Die Ausgabe wird im ⎕SMFenster angezeigt . Die Simulation läuft endlos. Das Raster ist 79x25, da dies die Standardgröße des ⎕SMFensters ist. Der Elektronenkopf ist h, Schwanz ist t, Kupfer ist c. Das Programm liest die Startkonfiguration als 25 Zeilen von der Tastatur.

Erläuterung:

  • ↑{79↑⍞}¨⍳25: Lies das 79x25 Raster
  • h t c←1↓⍵∘=¨F←' htc': Holen Sie sich drei Matrizen, eine mit den Köpfen, eine mit den Schwänzen und eine mit dem Kupfer. Setzen Sie auch F auf die Zeichenfolge ' htc'.

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: Der Teil "..." ist ein Vektor der Länge drei, bei dem die Elemente Matrizen sind, die die neuen Köpfe, Schwänze und Kupfer zeigen. Die Köpfe werden mit 1, die Schwänze mit 2 und das Kupfer mit 3 multipliziert, dann addieren wir diese Matrizen und ergeben eine Indexmatrix F. Nwird zum neuen Status im selben Format wie die Eingabe und wird auf dem ⎕SMBildschirm angezeigt, beginnend mit der oberen linken Ecke.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Fügen Sie einen Rand aus Leerzeichen hinzu, hindem Sie ihn um zwei Zeilen und Spalten vergrößern und dann eine nach rechts und eine nach unten drehen.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Drehen Sie die Matrix in alle acht Richtungen und addieren Sie dann die resultierenden Matrizen, um die Anzahl der Nachbarn zu ermitteln, die sich auf jeder Position befinden.

  • 1 2∊⍨: Setzen Sie nur die Positionen auf 1, die 1 oder 2 Nachbarn haben.

  • S↑1 1↓: Entfernen Sie den Rand, den wir zuvor hinzugefügt haben.

  • H←c∧: Die neuen Köpfe sind alle Kupferzellen, die 1 oder 2 Kopfnachbarn haben.

  • t∨c≠H: Die neuen Kupferzellen sind alle alte Schwänze und alle alten Kupferzellen, die nicht zu Köpfen geworden sind.

  • H h(... ): Die neuen Köpfe sind Hwie oben berechnet, die neuen Schwänze sind die alten Köpfe und die neuen Kupferzellen sind wie oben berechnet.

  • ∇N⊣⎕DL÷4: Warten Sie eine viertel Sekunde und führen Sie die Funktion dann erneut aus N.


Ich denke, es wäre besser, wenn es ein 40 x 40-Raster enthalten könnte.
mbomb007

6

ALPACA, 82 Zeichen

ALPACA ist eine Sprache, die speziell für zellulare Automaten entwickelt wurde.

o ist nichts; c ist Dirigent; e ist Elektron; t ist der Elektronenschwanz.

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

Wann wurde diese Sprache veröffentlicht? Gibt es Links für die Sprache?
Optimierer

@Optimizer Los geht's! Ich habe die Sprache nicht gemacht.
DanTheMan

4
Cool. Die richtige Sprache für die richtige Herausforderung ..
Optimierer

4

GolfScript ( 125 120 105 100 Zeichen)

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

Beachten Sie, dass ich \033jeweils ein Zeichen zähle , da diese durch ein Literalzeichen ersetzt werden können ESC. Dies verwendet ANSI-Steuercodes, setzt also eine kompatible tty voraus. Beachten Sie auch, dass Frames ab dem Eingaberaster gedruckt werden.

Es gibt einige Überschneidungen mit der Option "Summenraster erstellen" , bei der auch die Nachbarschaft "Moore" verwendet wird.

Kodierung: Leerzeichen => ; Elektronenkopf => i; Elektronenschwanz => `; Kupfer => X.

Die Pause zwischen den Iterationen ist die Zeit, die zur Berechnung von 46656 und 46656 benötigt wird . Wenn Sie 6.?.?zu einem anderen Ausdruck wechseln , können Sie die Geschwindigkeit steuern. Das nächst langsamere für die gleiche Zeichenanzahl ist 7.?.?das viel langsamere (die Ausgabe ist 22-mal so groß und es handelt sich nicht um eine lineare Komplexitätsberechnung).

Für einen Testfall habe ich verwendet

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

von der Rosetta Code Wireworld Herausforderung.


3

Python 371 341 Zeichen

Ja, es ist nicht so kurz, aber es hat eine interaktive Benutzeroberfläche!

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

Anleitung:

Klicken Sie mit der linken Maustaste, um den Draht zu platzieren

Klicken Sie mit der rechten Maustaste, um zu löschen

Klicken Sie mit der mittleren Maustaste, um den Elektronenkopf zu platzieren

Klicken Sie außerhalb der Achsen, um den Automaten zu bewegen


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

3

Python ( 243 214)

Versucht, eine Kreuzung zwischen Benutzerfreundlichkeit und Charakteren zu machen. Das Raster ist 40x40. Die Eingabe erfolgt über stdin. Ein Elektronenkopf ist h, Elektronenschwanz ist t, Kupfer ist c, alles andere ist leer.

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

Die while-Schleife (Zeile 3) ist nicht komprimiert (funktioniert nicht, wenn sie im Code platziert ist):

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

Ich glaube , Sie können Linien ersetzen 5-7 mit einem einzigen Ausdruck: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. Ich
bin

2

C 355 347 300 294 Zeichen

Edit: realisiert das brauche ich nicht feof()

Bearbeiten: 47 Zeichen gespeichert! Entfernte den Schlaf, entfernte fast alle Zahnspangen, kombinierte viele Operationen.

Edit: Letzte heute, da ich 300 Zeichen gebrochen habe. Geändert printfzu puts, fand beim ersten Vergleich eine süße kleine Optimierung.

C eignet sich nicht gut für diese Art von Problem, aber hey, Golfen macht Spaß. Dies ist eine ziemlich gewaltige Implementierung, aber ich wollte sehen, wie weit ich damit Golf spielen kann.

Die Eingabe ist eine Textdatei mit dem Namen i. Es enthält eine Darstellung des Ausgangszustands mit *für Kupfer, +für Elektronenkopf, -für Elektronenschwanz, Leerzeichen für leere Zellen. Ich benutze das XOR-Gatter auf der Wiki-Seite zum Testen.

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

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

Könnte cond?43:42geschrieben werden 42+(cond)? Und ich bin sicher, r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;kann reduziert werden, r=s[j][i++];*p=r==43?45:r==45?42:r;wenn nichtr=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor

1

Python, 234 218 Zeichen

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)

Sie geben die Karte in Form von drei komplexen Zahlen ein, die die Koordinaten der Kupferzellen (die die Kopf- und Schwanzlisten enthalten müssen), Köpfe und Schwänze darstellen. Hier ist ein Beispiel:

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

Beachten Sie, dass wir evaldie Eingabe, so dass Sie für Listen komplexer Zahlen beliebig komplexe Ausdrücke verwenden können.


1

QBasic, 309 Bytes

Warnung: Die Golf-Version ist nicht benutzerfreundlich: Sie verfügt über eine seltsame Eingabemethode, wird als Endlosschleife ausgeführt und hat keine Verzögerung (läuft daher auf einigen Systemen zu schnell). Führen Sie es nur aus, wenn Sie wissen, wie Sie ein Programm in Ihrer QBasic-Umgebung beenden. Die ungolfed Version wird empfohlen (siehe unten).

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

Geben Sie zum Ausführen an der Eingabeaufforderung die Breite wund Höhe Ihrer Konfiguration an h. 1 Geben Sie dann w*heinstellige Codes für die Zellen ein (von links nach rechts, dann von oben nach unten), und drücken Sie

  • 0 = leer
  • 6 = Draht
  • 7 = Signalkopf
  • 1 = Signalschwanz

Sobald Sie alle Zellen eingegeben haben, beginnt die Simulation (und wird für immer fortgesetzt, bis Sie das Programm beenden).

Ungolfed

Eine benutzerfreundlichere Version. Ändern Sie zum Ändern des Layouts die DATAAnweisungen am Ende.

Der Code nutzt die POINTFunktion, die den Farbwert eines Pixels vom Bildschirm liest. Dies bedeutet, dass wir die Zellen nicht separat als Array speichern müssen. Um sicherzustellen, dass alle Zellen gleichzeitig aktualisiert werden, führen wir die Aktualisierungen auf einer zweiten "Seite" durch. Wir können die aktive Seite mit einer Version der SCREENAnweisung umschalten und den Inhalt einer Seite mit der PCOPYAnweisung in eine andere kopieren .

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 Die Maximalwerte für Breite und Höhe hängen davon ab, welcher Bildschirmmodus verwendet wird. In SCREEN 9kann die Breite bis zu 638 und die Höhe bis zu 348 SCREEN 7betragen. Hat eine kleinere Auflösung (maximale Konfigurationsgröße 318 mal 198), aber die Pixel sind größer und daher leichter zu erkennen (auf DOS QBasic oder dem DOSBox-Emulator - leider nur auf QB64) ergibt ein kleineres Fenster).

Beispiellauf

Ungolfed-Version auf archive.org , mit Bildschirmmodus 7:

Wireworld in QBasic

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.