模拟Wireworld元胞自动机


24

Wireworld是一种细胞自动机,其设计类似于流过电线的电子。它的简单机制允许构建数字电路。它甚至允许建造整个计算机

您的任务是使用您选择的语言创建最短的Wireworld实现。

网格中的每个单元都有四个状态之一。四个状态为“空白”,“铜”,“电子头”或“电子尾”。

  • 空白单元格将始终是空白单元格
  • 电子头永远变成电子尾
  • 电子尾巴将永远变成铜
  • 如果一个铜电池中的八个邻居中恰好有一个或两个是电子头,它将变成一个电子头,否则它将保持为铜

这项比赛的风格与“ 最短生命游戏”比赛类似,但有一些变化。

  • 网格必须至少为40 x 40单元
  • 网格的边缘不能环绕(不是圆环)。将场外的细胞视为不断“空白”。
  • 用户必须有可能输入自己的启动配置。
  • 盯着黑屏不好玩。该程序必须在运行时直观地显示模拟。

这是代码高尔夫,最少的字节数获胜。

Answers:


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,尾是tc。程序从键盘读取25行的启动配置。

说明:

  • ↑{79↑⍞}¨⍳25:读取79x25网格
  • h t c←1↓⍵∘=¨F←' htc':得到三个矩阵,一个带有头部,一个带有尾巴,另一个带有铜。同时将F设置为字符串' htc'

  • ⎕SM∘←1 1,⍨⊂N←F[1+⊃+/... ר⍳3]:“ ...”部分是长度为三的向量,其中元素是分别显示新的头,尾和铜的矩阵。将头乘以1,将尾巴乘以2,将铜乘以3,然后将这些矩阵相加并加一,得到索引矩阵FN变成新状态,格式与输入相同,并⎕SM从左上角开始显示在屏幕上。

  • ¯1⌽¯1⊖h↑⍨2+S←25 79:通过将空白边框h增加两行和两列,然后向右旋转和向下旋转来添加边框。

  • ⊃+/+/K∘.⊖(K←2-⍳3)∘.⌽⊂:沿所有八个方向旋转矩阵,然后将所得矩阵求和,得出每个位置上都是正面的邻居的数量。

  • 1 2∊⍨:仅将具有1个或2个邻居的位置设置为1。

  • S↑1 1↓:删除我们之前添加的边框。

  • H←c∧:新的磁头是所有具有1个或2个磁头邻居的铜电池。

  • t∨c≠H:新的铜电池都是旧的尾巴,而所有尚未变成头部的旧的铜电池。

  • H h(…… ):新的头是H如上计算的,新的尾部是旧的头,而新的铜制电池是如上的计算。

  • ∇N⊣⎕DL÷4:等待1/4秒,然后在上再次运行该功能N


我认为最好包含40 x 40的网格。
mbomb007'7

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

@Optimizer,您在这里!我没有讲语言。
DanTheMan

4
凉。用正确的语言来应对正确的挑战
Optimizer

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。还要注意,帧是从输入网格开始打印的。

生成总和网格有一些重叠,该网格也使用Moore邻域。

编码:空白=> ; 电子头=> i; 电子尾=> `; 铜=> X

迭代之间的暂停是计算46656 46656所需的时间。更改6.?.?为另一个表达式可以控制速度。对于相同字符数7.?.?,下一个最慢的是,它慢得多(输出是22倍,不是线性复杂度计算)。

对于一个测试用例,我一直在使用

`iXXXXXXXXX
X   X      
   XXX     
X   X      
i`XX XXXXXX

来自Rosetta Code Wireworld挑战。


3

Python 371341个字符

是的,还不算短,但是它有一个交互式的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()

说明:

用鼠标左键单击以放置电线

用鼠标右键单击以清除

用鼠标中键单击以放置电子头

在轴外单击以步进自动机


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

3

蟒蛇(243214

试图在可用性和字符之间进行区分。网格为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

while循环(第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个字符。更改printfputs,通过第一个比较发现了一个可爱的小优化。

C不能很好地解决此类问题,但是,打高尔夫很有趣。这是一个蛮力的实现,但是我想看看我能打多远。

输入是一个名为的文本文件i。它包含初始状态的表示形式,其中包括*用于铜,+用于电子头,-用于电子尾,用于空单元的空间。我正在使用Wiki页面上的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:4242+(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个字节

警告:高尔夫球版本不是用户友好的:它具有一种怪异的输入法,可以无限循环运行,并且没有任何延迟(因此,在某些系统上运行太快)。仅当您知道如何在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

要运行,请在输入提示下指定配置的width w和height h1然后输入w*h单元格的一位数字代码(从左到右,然后从上到下移动),用

  • 0 =空
  • 6 =电线
  • 7 =信号头
  • 1 =信号尾

输入所有单元格后,模拟将开始(并一直持续到您终止程序为止)。

不打高尔夫球

一个更加用户友好的版本。要修改布局,请最后修改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 x 198),但是像素较大,因此更易于查看(在DOS QBasic或DOSBox仿真器上-不幸的是,QB64仅给出一个较小的窗口)。

运行示例

屏幕模式7 上archive.org上的取消发布版本:

QBasic中的Wireworld

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.