模拟任何一维元胞自动机


14

挑战

您将要编写一个完整的程序,该程序使用来自STDIN的七个数字,并将元胞自动机(CA)的二维历史记录打印到STDOUT。这是代码高尔夫。

输入格式 输入将是七个整数/字符串,以逗号分隔。第一个数字是根据Wolfram代码的规则编号(每个规则的标准名称)。第二个是初始启动配置。第三个和第四个描述了什么模式以及应将多少模式附加到启动配置的左侧。作为填充。第五和第六在右侧也是如此。最后一个数字是运行模拟的世代数。

因此,输入示例为90,11,0,4,0,4,5。这应该告诉您的程序您正在运行规则90。它还应该告诉程序您希望初始配置是11在字符串的0两端都附加4次,因此实际的开始模式是0000110000。它还告诉您的程序将此模拟运行5代。

输出您的程序应该打印每一代的整个单元格数组(用换行符分隔),以便输出是CA的时空图。对于每一代,根据作为输入提供的规则,每个单元的状态由其状态和紧靠左侧和右侧的单元的状态确定。模拟应围绕边缘。首先打印的应该是gen的起始数组。0。

输入90,11,0,4,0,4,5应尽可能精确地产生以下输出。

0000110000
0001111000
0011001100
0111111110
1100000011
0110000110

请注意,起始状态不包括在五代中。还要注意,模拟环绕着边缘。

更多例子

输入:

184,1100,01,2,01,1,4

输出:

0101110001
1011101000
0111010100
0110101010
0101010101

输入:

0,1011,1,0,0,1,2

输出:

10110
00000
00000

有关一维CA如何工作以及如何编号的更多信息


将规则0包含在测试案例中做得很好。
彼得·泰勒

我对规则90是Sierpinski垫片非常着迷。特别是因为这是我为另一个Codegolf项目所做的测试的一部分。
JoeFish 2012年

@JoeFish是您的图像使我尝试了这一操作。我想给出8086的答案-杀死2只鸟-但它可能需要进行字符串操作,因此我的模拟器无法运行它(至今)。
luser droog 2012年

Answers:


5

Golfscript,77 73 70个字符

','/)~\(~:?;~~*@@~*@+\+{1&}/]({[.,{.[3<?256+]{2base}/\~=\(+}*])n@)\+}*

感谢@Howard,他指出了如何保存4个字符。


您可以保存一个显而易见的48--> 1&我想还可以保存三个。您可以)在块之前省略(不增加计数器),因此也可以保存最后两个弹出窗口。
霍华德

@霍华德,谢谢。最后的那些流行音乐在较早的迭代中很有用,但您是对的,现在消除它们是正确的。
彼得·泰勒

5

APL(153个字符)

∇ cellularautomaton
  i               ← ⍞
  s               ← (i=',') / ⍳ ⍴i
  (b a x c)       ← {i[s[⍵]↓⍳s[⍵+1]-1]} ¨ ⍳4
  (z x x l x r n) ← ⍎i
  y               ← ⍎ ¨ ⊃ ,/ (l / ⊂a) , b , r / ⊂c
  (n+1) (⊃⍴,y) ⍴ '01'[1+⊃ ,/ y,{({(z ⊤⍨ 8/2)[8 - 2⊥¨ 3 ,/ (⊃⌽⍵),⍵,⊃⍵]}⍣⍵)y} ¨ ⍳n]
∇

且可读性较低,形式略短:

i←⍞⋄s←(i=',')/⍳⍴i⋄b a x c←{i[s[⍵]↓⍳s[⍵+1]-1]}¨⍳4⋄z x x l x r n←⍎i⋄y←⍎¨⊃,/(l/⊂a),b,r/⊂c⋄'01'[1+⊃,/y,{({(z⊤⍨8/2)[8-2⊥¨3,/(⊃⌽⍵),⍵,⊃⍵]}⍣⍵)y}¨⍳n]⍴⍨(1+n),⊃⍴,y

例:

      cellularautomaton
26,00110,01,4,10,6,7
0101010100110101010101010
1000000011100000000000001
0100000110010000000000011
0010001101101000000000110
0101011001000100000001101
0000010110101010000011000
0000100100000001000110100
0001011010000010101100010

我敢肯定还有改进的余地(我在写这篇文章时甚至发现了一些更改!),但是其中一些可能涉及到根本性的更改,我再也不能盯着APL了。这里使用的APL的变体是Dyalog APL


4

Ruby,165159个字符

a=gets.split ?,
b=a.map &:to_i
c=(x=a[2]*b[3]+a[1]+a[4]*b[5]).chars.map &:hex
(0..b[6]).map{puts c*''
c=(1..w=x.size).map{|i|b[0]>>c[i-1]*2+c[i%w]+c[i-2]*4&1}}

编辑:我发现了一些小的增强功能的地方。

示例运行:

> 30,1,0,20,0,20,20
00000000000000000000100000000000000000000
00000000000000000001110000000000000000000
00000000000000000011001000000000000000000
00000000000000000110111100000000000000000
00000000000000001100100010000000000000000
00000000000000011011110111000000000000000
00000000000000110010000100100000000000000
00000000000001101111001111110000000000000
00000000000011001000111000001000000000000
00000000000110111101100100011100000000000
00000000001100100001011110110010000000000
00000000011011110011010000101111000000000
00000000110010001110011001101000100000000
00000001101111011001110111001101110000000
00000011001000010111000100111001001000000
00000110111100110100101111100111111100000
00001100100011100111101000011100000010000
00011011110110011100001100110010000111000
00110010000101110010011011101111001100100
01101111001101001111110010001000111011110
11001000111001111000001111011101100010001

3

C,303 305 301 294 292

305编辑:哎呀。忘了带calloc()两个参数。随着更大的投入,它开始爆炸。

301编辑:啊哈!我的calloc()boo-boo通过增加请求的内存的块大小来节省2个字节。

294编辑:打破了300!消除了之一,strcat()并调整了一些循环。获得了最大的嚼食,这和使用一样有趣。

292编辑:不需要+2内存分配。

使用luser droog的答案作为基本思想,但更改了包装算法,并对常量进行了许多调整和分解。

r,A,C,n,j;main(){char*s,*p,*t,a[9],b[9],c[9];scanf("%d,%[01],%[01],%d,%[01],%d,%d",&r,b,a,&A,c,&C,&n);for(s=calloc(A+++C,9);A--;)strcat(s,A?a:b);for(;C--;)strcat(s,c);p=strdup(s);for(C=strlen(s);A++<n;puts(s),t=p,p=s,s=t)for(j=C;j--;)p[j]=(1<<(s[j?j-1:C-1]*4+s[j]*2+s[(j+1)%C])-336)&r?49:48;}

r,A,C,n,j;
main(){
    char*s,*p,*t,a[9],b[9],c[9];
    scanf("%d,%[01],%[01],%d,%[01],%d,%d",&r,b,a,&A,c,&C,&n);
    for(s=calloc(A+++C,9);A--;)
        strcat(s,A?a:b);
    for(;C--;)
        strcat(s,c);
    p=strdup(s);
    for(C=strlen(s);A++<n;puts(s),t=p,p=s,s=t)
        for(j=C;j--;)
            p[j]=(1<<(s[j?j-1:C-1]*4+s[j]*2+s[(j+1)%C])-336)&r?49:48;
}

屏幕截图1

屏幕截图2


1
您忘了开始C,A,!:)
luser droog 2012年

对于大量的内存brk()呢?然后在p=s+C+1;某个地方。
luser droog 2013年

1
再次+1以使用+++
luser droog

哈哈!改变所有的%[01]%s!-9(...很多年后)
luser droog '17年

1
@luserdroog这是行不通的,因为%s贪婪,并且也吃逗号和其他数字。
JoeFish

2

C (487 484 418(删除空格)

* 在JoeFish的帮助下下降了66个 *

C,A,r,n,j;main(){char*s,*p,*t,a[9],b[9],c[9];
    scanf("%d,%[01],%[01],%d,%[01],%d,%d",&r,b,a,&A,c,&C,&n);
    s=malloc(strlen(a)*A+strlen(b)+strlen(c)*C+3);*s=0;
    strcat(s,"0");
    for(;A--;)strcat(s,a);
    strcat(s,b);
    for(;C--;)strcat(s,c);
    strcat(s,"0");
    p=malloc((C=strlen(s)-1)+2);
    for(;n--;){
    *s=s[C-1];
    s[C]=0;
    puts(s+1);
    s[C]=s[1];
    for(j=1;s[j+1];j++)
        p[j]=(1<<(s[j-1]-48)*4+(s[j]-48)*2+s[j+1]-48)&r?49:48;
    t=p;p=s;s=t;
    }
    s[C]=0;
    puts(s+1);
}

打字稿

josh @ Z1〜
$!m
使ca
cc ca.c -o ca
ca.c:1:1:警告:数据定义没有类型或存储类
ca.c:在“ main”函数中:
ca.c:2:5:警告:内置函数'scanf'的隐式声明不兼容
ca.c:3:7:警告:内置函数'malloc'的隐式声明不兼容
ca.c:3:14:警告:内置函数“ strlen”的隐式声明不兼容
ca.c:4:5:警告:内置函数'strcat'的隐式声明不兼容

josh @ Z1〜
$ echo 90,11,0,4,0,4,5 | 钙
-bash:ca:找不到命令

josh @ Z1〜
$ echo 90,11,0,4,0,4,5 | ./ca
0000110000
0001111000
0011001100
0111111110
1100000011
0110000110


真好 您可以通过使int变量成为全局变量并删除以下内容来剃掉很多字节#includer,A,B,C,n,i,j; main(){char *s...
JoeFish 2012年

for循环中保存一堆:for(;A--;)strcat(s,a);
JoeFish 2012年

和再利用A以及C后来这样你就不必申报iB在所有。p=malloc((C=strlen(s))+1); --C; strcpy(p,s); for(A=0;A<n;A++){抱歉,我现在停止:)
JoeFish 2012年

好吧,我撒谎了。通过消除--C;:摆脱2个障碍p=malloc((C=strlen(s)-1)+2);。我认为高尔夫代码比最初提出它更有趣!
JoeFish 2012年

我不确定要删除,#include因为它scanf是可变的。但这可能还可以,因为它只被调用了一次。...我的旧机器昨天死了,我仍在安装Cygwin。我将尽快测试这些变更。谢谢!
luser droog
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.