Simulasikan otomat seluler Wireworld

24

Wireworld adalah otomat seluler yang dirancang menyerupai elektron yang mengalir melalui kabel. Mekaniknya yang sederhana memungkinkan pembangunan sirkuit digital. Bahkan memungkinkan pembangunan seluruh komputer .

Misi Anda adalah menciptakan implementasi Wireworld terpendek dalam bahasa pilihan Anda.

Setiap sel di grid memiliki satu dari empat negara. Keempat negara bagian itu "kosong," "tembaga," "kepala elektron," atau "ekor elektron."

  • Sel kosong akan selalu menjadi sel kosong
  • Kepala elektron akan selalu menjadi ekor elektron
  • Ekor elektron akan selalu menjadi tembaga
  • Sel tembaga akan menjadi kepala elektron jika hanya satu atau dua dari delapan tetangganya adalah kepala elektron, jika tidak maka akan tetap tembaga

Kompetisi ini akan memiliki gaya yang mirip dengan kompetisi Game Terpendek Kehidupan , tetapi dengan beberapa perubahan.

  • Grid harus setidaknya 40 kali 40 sel
  • Tepi kisi harus TIDAK membungkus (bukan torus). Perlakukan sel di luar bidang sebagai "kosong" terus-menerus.
  • Harus memungkinkan bagi pengguna untuk memasukkan konfigurasi awal mereka sendiri.
  • Menatap layar kosong tidak menyenangkan. Program harus secara visual menampilkan simulasi ketika sedang berjalan.

Ini adalah kode golf, byte paling sedikit menang.

PhiNotPi
sumber

Jawaban:

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

Outputnya ditampilkan di ⎕SMjendela. Simulasi berjalan tanpa akhir. Kisi adalah 79x25 karena itulah ukuran standar ⎕SMjendela. Kepala elektron adalah h, ekor adalah t, tembaga c. Program membaca konfigurasi awal dari keyboard sebagai 25 baris.

Penjelasan:

  • ↑{79↑⍞}¨⍳25: baca kisi 79x25
  • h t c←1↓⍵∘=¨F←' htc': dapatkan tiga matriks, satu dengan kepala, satu dengan ekor dan satu dengan tembaga. Juga atur F ke string ' htc'.

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: Bagian "..." adalah vektor dengan panjang tiga, di mana elemen-elemennya adalah matriks yang menunjukkan masing-masing kepala, ekor, dan tembaga yang baru. Kepala dikalikan dengan 1, ekor dengan 2, dan tembaga dengan 3, maka kita menjumlahkan matriks ini bersama-sama dan menambahkan satu, memberikan matriks indeks ke dalam F. Nmenjadi status baru, dalam format yang sama dengan input, dan ditampilkan di ⎕SMlayar mulai dari sudut kiri atas.

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: Tambahkan batas kosong hdengan menumbuhkannya dengan dua baris dan kolom, lalu putar satu ke kanan dan satu ke bawah.

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: Putar matriks di semua delapan arah dan kemudian jumlah matriks yang dihasilkan bersama, memberikan jumlah tetangga yang berada di kepala pada setiap posisi.

  • 1 2∊⍨: Atur hanya posisi tersebut ke 1 yang memiliki 1 atau 2 tetangga.

  • S↑1 1↓: Hapus perbatasan yang kami tambahkan sebelumnya.

  • H←c∧: Kepala baru adalah semua sel tembaga yang memiliki 1 atau 2 kepala tetangga.

  • t∨c≠H: Sel tembaga baru semuanya adalah ekor lama, dan semua sel tembaga tua yang belum menjadi kepala.

  • H h(... ): Kepala baru Hdihitung di atas, ekor baru adalah kepala lama, dan sel tembaga baru dihitung di atas.

  • ∇N⊣⎕DL÷4: Tunggu 1/4 detik, lalu jalankan kembali fungsi N.

marinus
sumber
Saya pikir akan lebih baik jika bisa memuat 40 dengan 40 grid.
mbomb007
6

ALPACA, 82 karakter

ALPACA adalah bahasa yang dirancang khusus untuk otomat seluler.

o bukan apa-apa; c adalah konduktor; e adalah elektron; t adalah ekor elektron.

state o " ";
state c "c" to e when 1 e or 2 e;
state e "e" to t;
state t "t" to c.
DanTheMan
sumber
Kapan bahasa ini dirilis? Apakah ada tautan untuk bahasa ini?
Pengoptimal
@Optimizer Ini dia! Saya tidak membuat bahasa.
DanTheMan
4
Keren. Bahasa yang tepat untuk tantangan yang tepat ..
Pengoptimal
4

GolfScript ( 125 120 105 100 karakter)

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

Perhatikan bahwa saya menghitung \033masing-masing sebagai satu karakter, karena mereka dapat digantikan oleh ESCkarakter literal . Ini menggunakan kode kontrol ANSI, jadi andalkan tty yang kompatibel. Perhatikan juga bahwa frame dicetak mulai dengan kisi masukan.

Ada beberapa tumpang tindih dengan Generate grid of the sums , yang juga menggunakan lingkungan Moore.

Pengkodean: ruang kosong => ; kepala elektron => i; ekor elektron => `; tembaga => X.

Jeda antara iterasi adalah waktu yang diperlukan untuk menghitung 46656 46656 . Mengubah 6.?.?ke ekspresi lain memungkinkan Anda untuk mengontrol kecepatan; yang paling lambat berikutnya untuk jumlah karakter yang sama adalah 7.?.?, yang jauh lebih lambat (outputnya 22 kali lebih besar, dan itu bukan perhitungan kompleksitas linier).

Untuk test case, saya sudah menggunakan

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

dari tantangan Rosetta Code Wireworld .

Peter Taylor
sumber
3

Python 371 341 karakter

Ya, ini tidak sesingkat itu, tetapi memiliki gui interaktif!

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

Instruksi:

Klik dengan tombol kiri mouse untuk memasang kawat

Klik dengan tombol kanan mouse untuk menghapus

Klik dengan tombol tengah mouse untuk menempatkan kepala elektron

Klik di luar sumbu untuk melangkah otomat

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

Python ( 243 214)

Mencoba membuat persilangan antara kegunaan dan karakter. Kotak adalah 40x40. Masukan diberikan pada stdin. Kepala elektron adalah h, ekor elektron adalah t, tembaga adalah c, yang lainnya kosong.

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

Loop sementara (baris 3) tidak terkompresi (tidak akan berfungsi jika ditempatkan dalam kode):

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
sumber
Saya pikir Anda dapat mengganti garis 5-7 dengan ekspresi tunggal: g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else i. Tidak yakin apakah itu bekerja persis seperti apa adanya, tetapi sesuatu di sepanjang garis itu harus bekerja
Strigoides
2

C, 355 347 300 294 karakter

Sunting: menyadari saya tidak perlu feof()

Sunting: Disimpan 47 karakter! Removed the Sleep, menghilangkan hampir semua kawat gigi, menggabungkan banyak operasi.

Sunting: Terakhir hari ini, sejak saya memecahkan 300 karakter. Diubah printfmenjadi puts, ditemukan optimasi kecil yang lucu dengan perbandingan pertama.

C tidak cocok untuk masalah semacam ini, tapi hei, bermain golf itu menyenangkan. Ini adalah implementasi yang sangat kasar, tetapi saya ingin melihat sejauh mana saya bisa menggunakannya.

Input adalah nama file teks i. Ini berisi representasi dari keadaan awal, dengan *untuk tembaga, +untuk kepala elektron, -untuk ekor elektron, ruang untuk sel kosong. Saya menggunakan gerbang XOR dari halaman wiki untuk pengujian.

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

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
sumber
Bisa cond?43:42ditulis 42+(cond)? Dan saya yakin r=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;dapat dikurangi menjadi r=s[j][i++];*p=r==43?45:r==45?42:r;jika tidakr=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor
1

Python, 234 218 karakter

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)

Anda memasukkan papan sebagai tiga daftar bilangan kompleks yang mewakili koordinat sel tembaga (yang harus menyertakan daftar kepala dan ekor), kepala, dan ekor. Ini sebuah contoh:

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

Perhatikan bahwa kita evalinput, sehingga Anda dapat menggunakan ekspresi kompleks sewenang-wenang untuk daftar bilangan kompleks.

Keith Randall
sumber
1

QBasic, 309 byte

Peringatan: versi golf tidak ramah-pengguna: ia memiliki metode input yang aneh, berjalan sebagai loop tak terbatas, dan tidak memiliki penundaan (dengan demikian, berjalan terlalu cepat pada beberapa sistem). Jalankan saja jika Anda tahu cara menghentikan program di lingkungan QBasic Anda. Versi ungolfed direkomendasikan (lihat di bawah).

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

Untuk menjalankan, tentukan di input prompt lebar wdan tinggi konfigurasi Anda h. 1 Kemudian ketikkan w*hkode satu digit untuk sel (bergerak dari kiri ke kanan, lalu dari atas ke bawah), dengan

  • 0 = kosong
  • 6 = kawat
  • 7 = kepala sinyal
  • 1 = sinyal ekor

Setelah Anda memasukkan semua sel, simulasi akan dimulai (dan berlanjut selamanya, sampai Anda mematikan program).

Tidak disatukan

Versi yang lebih ramah pengguna. Untuk memodifikasi tata letak, ubah DATApernyataan di bagian akhir.

Kode mengambil keuntungan dari POINTfungsi, yang membaca nilai warna piksel dari layar. Ini berarti kita tidak perlu menyimpan sel secara terpisah sebagai array. Untuk memastikan bahwa semua sel memperbarui secara bersamaan, kami melakukan pembaruan pada "halaman" kedua. Kita dapat beralih halaman aktif menggunakan versi SCREENpernyataan, dan menyalin konten satu halaman ke yang lain menggunakan PCOPYpernyataan itu.

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 Nilai maksimum untuk lebar dan tinggi tergantung pada mode layar mana yang digunakan. Dalam SCREEN 9, lebar bisa hingga 638 dan tinggi hingga 348. SCREEN 7memiliki resolusi lebih kecil (ukuran konfigurasi maks 318 kali 198), tetapi pikselnya lebih besar dan karenanya lebih mudah dilihat (pada DOS QBasic atau emulator DOSBox - sayangnya QB64 hanya memberikan jendela yang lebih kecil).

Contoh dijalankan

Versi ungolfed di archive.org , dengan mode layar 7:

Wireworld di QBasic

DLosc
sumber