จำลองหุ่นยนต์เคลื่อนที่ของ Wireworld


24

Wireworldเป็นหุ่นยนต์อัตโนมัติที่ออกแบบมาให้มีลักษณะคล้ายอิเล็กตรอนที่ไหลผ่านสายไฟ กลไกง่าย ๆ ของมันช่วยให้การสร้างวงจรดิจิตอล มันได้รับอนุญาตแม้แต่การก่อสร้างของคอมพิวเตอร์ทั้งหมด

ภารกิจของคุณคือการสร้างการติดตั้ง Wireworld ที่สั้นที่สุดในภาษาที่คุณเลือก

แต่ละเซลล์ในกริดมีหนึ่งในสี่สถานะ สี่รัฐคือ "ช่องว่าง" "ทองแดง" "หัวอิเล็กตรอน" หรือ "หางอิเล็กตรอน"

  • เซลล์ว่างจะยังคงเป็นเซลล์ว่างเสมอ
  • หัวอิเล็กตรอนจะกลายเป็นหางอิเล็กตรอนเสมอ
  • หางอิเล็กตรอนจะกลายเป็นทองแดงเสมอ
  • เซลล์ทองแดงจะกลายเป็นหัวอิเล็กตรอนถ้าหนึ่งหรือสองในแปดเพื่อนบ้านเป็นหัวอิเล็กตรอนไม่เช่นนั้นจะยังคงอยู่ที่ทองแดง

การแข่งขันนี้จะมีรูปแบบคล้ายกับการแข่งขันShortest Game of Lifeแต่มีการเปลี่ยนแปลงเล็กน้อย

  • ตารางต้องมีอย่างน้อย 40 คูณ 40 เซลล์
  • ขอบของกริดต้องไม่พันกัน (ไม่ใช่ทอรัส) ปฏิบัติต่อเซลล์ภายนอกสนามว่า "ว่าง" อย่างต่อเนื่อง
  • ผู้ใช้ต้องป้อนการกำหนดค่าเริ่มต้นของตนเอง
  • การจ้องมองที่หน้าจอว่างเปล่านั้นไม่สนุก โปรแกรมต้องแสดงภาพจำลองขณะที่กำลังทำงาน

นี่คือรหัสกอล์ฟมีจำนวนน้อยที่สุดที่จะชนะ

คำตอบ:


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

ผลลัพธ์จะปรากฏขึ้นใน⎕SMหน้าต่าง การจำลองการทำงานไม่มีที่สิ้นสุด กริดคือ 79x25 เพราะนั่นคือขนาดเริ่มต้นของ⎕SMหน้าต่าง หัวอิเล็กตรอนhหางเป็นทองแดงt cโปรแกรมอ่านการกำหนดค่าเริ่มต้นจากแป้นพิมพ์เป็น 25 บรรทัด

คำอธิบาย:

  • ↑{79↑⍞}¨⍳25: อ่านตาราง 79x25
  • h t c←1↓⍵∘=¨F←' htc': รับสามเมทริกซ์, หนึ่งอันด้วยหัว, อันหนึ่งกับหางและอีกอันหนึ่งกับทองแดง ตั้ง F เป็นสตริง' htc'ด้วย

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]: ส่วน "... " เป็นเวกเตอร์ที่มีความยาวสามโดยที่องค์ประกอบคือเมทริกซ์ที่แสดงหัวใหม่ก้อยและทองแดงตามลำดับ หัวนั้นคูณด้วย 1 ก้อย 2 และทองแดงคูณ 3 จากนั้นเรารวมเมทริกซ์เหล่านี้เข้าด้วยกันแล้วบวกเข้าด้วยกันโดยให้เมทริกซ์ของดัชนีเข้าFมา Nจะกลายเป็นสถานะใหม่ในรูปแบบเดียวกับอินพุตและจะปรากฏบน⎕SMหน้าจอโดยเริ่มจากมุมบนซ้าย

  • ¯1⌽¯1⊖h↑⍨2+S←25 79: เพิ่มเส้นขอบของช่องว่างhโดยเพิ่มเป็นสองแถวและคอลัมน์จากนั้นหมุนไปทางขวาหนึ่งและหนึ่งด้านล่าง

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂: หมุนเมทริกซ์ในทั้งแปดทิศทางแล้วรวมเมทริกซ์ที่เกิดขึ้นพร้อมกันโดยให้จำนวนเพื่อนบ้านที่อยู่หัวในแต่ละตำแหน่ง

  • 1 2∊⍨: ตั้งค่าเฉพาะตำแหน่งเหล่านี้เป็น 1 ซึ่งมีเพื่อนบ้าน 1 หรือ 2 คน

  • S↑1 1↓: ลบเส้นขอบที่เราเพิ่มก่อนหน้านี้

  • H←c∧: หัวใหม่คือเซลล์ทองแดงทั้งหมดที่มีเพื่อนบ้าน 1 หรือ 2 หัว

  • t∨c≠H: เซลล์ทองแดงใหม่เป็นหางเก่าทั้งหมดและเซลล์ทองแดงเก่าทั้งหมดที่ไม่ได้เป็นหัว

  • H h(... ): หัวใหม่Hคำนวณตามข้างบนก้อยใหม่เป็นหัวเก่าและเซลล์ทองแดงใหม่คำนวณตามข้างบน

  • ∇N⊣⎕DL÷4: รอ 1/4 Nวินาทีแล้วเรียกใช้ฟังก์ชั่นอีกครั้งใน


ฉันคิดว่ามันคงจะดีกว่านี้ถ้ามันมีตาราง 40 คูณ 40
mbomb007

6

ALPACA, 82 ตัวอักษร

ALPACA เป็นภาษาที่ออกแบบมาสำหรับเซลลูล่าร์อัตโนมัติ

o ไม่มีอะไรเลย c คือตัวนำ e คืออิเล็กตรอน t คือหางอิเล็กตรอน

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

ภาษานี้เปิดตัวเมื่อใด มีลิงค์สำหรับภาษาหรือไม่
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ไปเลย! ฉันไม่ได้ทำภาษา
DanTheMan

4
เย็น. ภาษาที่เหมาะสมสำหรับความท้าทายที่เหมาะสม ..
เครื่องมือเพิ่มประสิทธิภาพ

4

GolfScript ( 125 120 105 100 ตัวอักษร)

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

หมายเหตุว่าฉันนับ\033เป็นหนึ่งในตัวละครแต่ละตัวเพราะพวกเขาจะถูกแทนที่ด้วยตัวอักษรESCตัวอักษร ใช้รหัสควบคุม ANSI ดังนั้นจึงต้องใช้ tty ที่ใช้ร่วมกันได้ โปรดทราบว่าเฟรมจะถูกพิมพ์เริ่มต้นด้วยกริดอินพุต

มีบางอย่างทับซ้อนกับสร้างผลรวมตารางซึ่งยังใช้พื้นที่ใกล้เคียงของมัวร์

การเข้ารหัส: blank space => ; หัวอิเล็กตรอน => i; หางอิเล็กตรอน => `; ทองแดง X=>

หยุดชั่วคราวระหว่างการทำซ้ำเป็นเวลาที่ต้องใช้ในการคำนวณ 46656 46656 การเปลี่ยน6.?.?เป็นนิพจน์อื่นให้คุณควบคุมความเร็ว ช้าที่สุดถัดไปสำหรับการนับตัวอักษรเดียวกันคือ7.?.?ซึ่งช้ากว่ามาก (ผลลัพธ์คือ 22 เท่าใหญ่และไม่ใช่การคำนวณความซับซ้อนเชิงเส้น)

สำหรับกรณีทดสอบฉันใช้ไปแล้ว

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

จากการท้าทายของRosetta Code Wireworld


3

Python 371 341 ตัวอักษร

ใช่มันไม่สั้น แต่มีกุยแบบโต้ตอบ!

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

คำแนะนำ:

คลิกด้วยปุ่มซ้ายของเมาส์เพื่อวางสาย

คลิกด้วยปุ่มเมาส์ขวาเพื่อล้าง

คลิกด้วยปุ่มกลางของเมาส์เพื่อวางหัวอิเล็กตรอน

คลิกที่นอกแกนเพื่อก้าวเข้าสู่หุ่นยนต์


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

3

Python ( 243 214)

พยายามที่จะข้ามระหว่างการใช้งานและตัวละคร ตารางคือ 40x40 อินพุตถูกกำหนดบน stdin หัวอิเล็กตรอนคือhหางอิเล็กตรอนคือtทองแดงคือcอะไรก็ได้ที่ว่างเปล่า

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

ขณะที่ลูป (บรรทัดที่ 3) ไม่มีการบีบอัด (จะไม่ทำงานหากวางไว้ในรหัส):

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

ฉันคิดว่าคุณสามารถเปลี่ยนสาย 5-7 g[e]='h'if(t=='c')&...else't'if i=='h'else'c'if i=='t'else iด้วยการแสดงออกเดียว: ไม่แน่ใจว่าสิ่งนี้ทำงานได้อย่างถูกต้องหรือไม่ แต่มีบางสิ่งในสายเหล่านั้นที่ใช้ได้
Strigoides

2

C, 355 347 300 294 ตัวอักษร

แก้ไข: รู้ว่าฉันไม่ต้องการ feof()

แก้ไข: บันทึก 47 ตัวอักษร! ลบการนอนหลับกำจัดวงเล็บปีกกาเกือบทั้งหมดรวมการดำเนินการจำนวนมาก

แก้ไข: ล่าสุดวันนี้เนื่องจากฉันทำลาย 300 ตัวอักษร เปลี่ยนprintfไปputsพบการเพิ่มประสิทธิภาพเล็ก ๆ น้อย ๆ ที่น่ารักด้วยการเปรียบเทียบครั้งแรก

C ไม่ได้ยืมตัวเองดีกับปัญหาแบบนี้ แต่เฮ้การเล่นกอล์ฟมันสนุก นี่เป็นการใช้งานที่ดุร้าย แต่ฉันต้องการดูว่าฉันสามารถตีกอล์ฟได้ไกลแค่ไหน

iการป้อนข้อมูลเป็นแฟ้มข้อความที่มีชื่อว่า มันประกอบด้วยการแสดงสถานะเริ่มต้น*สำหรับทองแดง+สำหรับหัว-อิเล็กตรอนสำหรับหางอิเล็กตรอนช่องว่างสำหรับเซลล์ว่าง ฉันใช้เกต XOR จากหน้าวิกิเพื่อทดสอบ

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

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

สามารถcond?43:42เขียนได้42+(cond)? และฉันแน่ใจว่าr=s[j][i++];*p=r==43?45:r;if(r==45)*p=42;สามารถลดลงr=s[j][i++];*p=r==43?45:r==45?42:r;ได้ถ้าไม่ใช่r=s[j][i++]-43;*p=!r?45:r==2?42:r;
Peter Taylor

1

Python 234 218 ตัวอักษร

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)

คุณป้อนบอร์ดเป็นรายการสามรายการของจำนวนเชิงซ้อนที่แสดงถึงพิกัดของเซลล์ทองแดง (ซึ่งจะต้องมีรายการหัวและก้อย) หัวและก้อย นี่คือตัวอย่าง:

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

โปรดทราบว่าเราevalเป็นอินพุตดังนั้นคุณสามารถใช้นิพจน์ที่ซับซ้อนโดยพลการสำหรับรายการตัวเลขที่ซับซ้อน


1

QBasic ขนาด 309 ไบต์

คำเตือน:เวอร์ชัน golfed นั้นไม่ได้ใช้งานง่าย: มันมีวิธีป้อนข้อมูลแปลก ๆ , ทำงานเป็นวนรอบไม่สิ้นสุดและไม่มีความล่าช้าใด ๆ (ดังนั้นจะทำงานเร็วเกินไปในบางระบบ) รันเฉพาะเมื่อคุณรู้วิธียกเลิกโปรแกรมในสภาพแวดล้อม QBasic ของคุณ ขอแนะนำให้ใช้เวอร์ชันที่ไม่ดี (ดูด้านล่าง)

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

ในการรันให้ระบุที่อินพุตพร้อมต์ความกว้างwและความสูงของการกำหนดค่าของhคุณ 1จากนั้นพิมพ์w*hรหัสตัวเลขเดียวสำหรับเซลล์ (เลื่อนจากซ้ายไปขวาจากนั้นเลื่อนจากบนลงล่าง) ด้วย

  • 0 = ว่างเปล่า
  • 6 = wire
  • 7 = หัวสัญญาณ
  • 1 = สัญญาณหาง

เมื่อคุณเข้าสู่เซลล์ทั้งหมดแล้วการจำลองจะเริ่มขึ้น (และดำเนินต่อไปเรื่อย ๆ จนกว่าคุณจะฆ่าโปรแกรม)

Ungolfed

รุ่นที่ใช้งานง่ายขึ้น หากต้องการแก้ไขเลย์เอาต์ให้แก้ไขDATAข้อความในตอนท้าย

รหัสใช้ประโยชน์จากPOINTฟังก์ชั่นซึ่งอ่านค่าสีของพิกเซลจากหน้าจอ ซึ่งหมายความว่าเราไม่จำเป็นต้องเก็บเซลล์แยกเป็นอาร์เรย์ เพื่อให้แน่ใจว่าเซลล์ทั้งหมดจะอัปเดตพร้อมกันเราจะทำการอัปเดตใน "หน้าสอง" เราสามารถสลับหน้าที่ใช้งานอยู่โดยใช้เวอร์ชันของSCREENคำสั่งและคัดลอกเนื้อหาของหน้าหนึ่งไปยังอีกหน้าโดยใช้PCOPYคำสั่ง

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ค่าสูงสุดสำหรับความกว้างและความสูงขึ้นอยู่กับโหมดหน้าจอที่ใช้ ในSCREEN 9ความกว้างอาจสูงถึง 638 และสูงถึง 348 SCREEN 7มีความละเอียดน้อยกว่า (ขนาดการกำหนดค่าสูงสุด 318 โดย 198) แต่พิกเซลมีขนาดใหญ่กว่าและง่ายต่อการดู (บน DOS QBasic หรือโปรแกรมจำลอง DOSBox - น่าเสียดายที่ QB64 เพียง ให้หน้าต่างเล็กลง)

ตัวอย่างการวิ่ง

เวอร์ชันที่ไม่ได้อัปโหลดในarchive.orgพร้อมโหมดหน้าจอ 7:

Wireworld ใน QBasic

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.