伪随机细胞自动机


14

介绍

在这个挑战中,我们将使用非常差的伪随机数来模拟某个概率的细胞自动机。元胞自动机是通过以下本地规则在二进制字符串上定义的。假设一个单元格的左邻居和该单元格本身具有状态ab

  • 如果为min(a,b) == 0,则的新状态bmax(a,b)
  • 如果为min(a,b) == 1,则b从中随机选择的新状态{0,1}

下图显示了单个的可能的10步演变1

1
11
101
1111
11001
101011
1111111
10001001
110011011
1010111101

请注意,两个相邻的1s有时如何演变为1,有时演变为,并且0最边界位始终1是s。您的任务是产生这种形式的细胞自动机进化。

输入项

您的输入是一个正整数n(表示要显示的行数),以及一个非空的位列表(L我们将其用作随机性来源)。

输出量

您的输出是一个列表列表或2D位数组,如上图所示,描述了单个对象1n时间步长上的演变。0如果需要,可以用s 填充输出以获取相等长度的行,但不能以0s开头。

元胞自动机中的随机选择必须从列表中得出,L用尽时会跳回到开头。更明确地讲,如果输出从上到下,从左到右一次遍历一行,那么连续的随机选择将形成L重复所需次数的列表。

假设输入是n = 7L = [0,1,0]。然后,细胞自动机在以下7个步骤中演化如下,其中我们v在每个随机选择上方都放置了一个右键:

[1]

[1,1]
   v
[1,0,1]

[1,1,1,1]
   v v v
[1,1,0,0,1]
   v
[1,1,1,0,1,1]
   v v   v
[1,0,0,1,1,1,1]

如果我们读取所有标有a的位,则会v得到01001001,该值L重复2.66次。下一个随机位是0

规则和计分

您可以编写完整的程序或函数。最低字节数获胜,并且不允许出现标准漏洞。输入和输出的确切格式不重要(在合理范围内)。

测试用例

确定性版本,每个随机位是0

Inputs: 10 [0]
Output:
1
11
101
1111
10001
110011
1010101
11111111
100000001
1100000011

每个随机位是1

Inputs: 6 [1,1]
Output:
1
11
111
1111
11111
111111

伪随机版本:

Inputs: 10 [0,0,1]
Output:
1
11
101
1111
10101
111111
1010011
11110101
101011111
1111101001

Inputs: 10 [1,0,0,1]
Output:
1
11
111
1001
11011
111111
1001101
11010111
111111101
1011001111

Inputs: 15 [1,1,1,0,0,0]
Output:
1
11
111
1111
10001
110011
1110111
11011001
111111011
1100011111
11100100011
111101100101
1001111101111
11011000111111
101101001011101

Answers:


3

Pyth,33个字节

jjLk.u++1m?hSde=.<Q1sd.:N2 1tvz]1

在线尝试:演示测试套件

说明:

jjLk.u++1m?hSde=.<Q1sd.:N2 1tvz]1  implicit: Q = input list
    .u                      tvz]1  reduce N=[1] input-1 times by applying
                      .:N2           all substrings of length 2
         m                           map each d of ^ to:
          ?hSd                         if min(d) = 0 then:
               =.<Q1                     rotate Q by one
              e                          and use the last element
                    sd                 else use sum(d) (=max(d))
      ++1                  1         add a 1 at the front and the back
                                   .u gives all intermediate results
 jLk                               join these lists to strings
j                                  print each string on a line

7

视网膜,139字节

^.
1

 00:0 01:1 10:1 11:
(m`^(..)((\S*)(?<=0) .*)
$1$3#$1!$2
+m`(?<=^(?<-2>.)*(..).*?#(.)*.)\d!(.)(.*\1:)(.)(\d*)
$5$3!$4$6$5
)`!0
0
 .+
<empty>

其中<empty>表示存在尾随的空行。每行都放在一个单独的文件中,并且#应将其替换为换行符(0x0A)。

预计该输入是n一元(由零组成,如在一元),后跟一个空格,其次是“伪随机”的字符串,例如10, [1, 0, 0, 1]将被理解为

0000000000 1001

输出就像在挑战中一样,但是用零填充,例如

1000000000
1100000000
1110000000
1001000000
1101100000
1111110000
1001101000
1101011100
1111111010
1011001111

这比我预期的要复杂得多。


3

Python中,142 135 132 131字节

133 132 131字节版本

f=input;n=f();L=f()*n*n;r=[1];i=1
while i<=n:print r;r=[L.pop(0)if r[x-1]&r[x]else r[x-1]+r[x]for x in range(1,i)];r=[1]+r+[1];i+=1

已取代 r[x-1]+r[x]>1r[x-1]&r[x]按位运算符并产生的最小值(r[x-1],r[x])

感谢@ThomasKwa的建议 n*n而不是n**2节省1个字节!

感谢@Shebang的-1字节

135字节版本

f=input;n=f();L=f()*n**2;r=[1];i=1
while i<=n:print r;r=[L.pop(0)if r[x-1]+r[x]>1 else r[x-1]+r[x]for x in range(1,i)];r=[1]+r+[1];i+=1

感谢@Cole提供了-7个字节:

min(r[x-1],r[x])->r[x-1]+r[x]>1

max(r[x-1],r[x])->r[x-1]+r[x]

142字节版本

f=input;n=f();L=f()*n**2;r=[1];i=1
while i<=n:print r;r=[L.pop(0)if min(r[x-1],r[x])else max(r[x-1],r[x])for x in range(1,i)];r=[1]+r+[1];i+=1

甚至没有接近@Jakube的答案,但是我在编写和打高尔夫球这一过程中获得了很多乐趣。

需要两个输入:第一个输入是行数,第二个输入是伪随机源列表。它在控制台上一行又一行地打印,每一行都换一行。

举个例子:

10 # This is input
[0] # This is input
[1] <- First output row
[1, 1]
[1, 0, 1]
[1, 1, 1, 1]
[1, 0, 0, 0, 1]
[1, 1, 0, 0, 1, 1]
[1, 0, 1, 0, 1, 0, 1]
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 0, 0, 0, 0, 0, 0, 1, 1]

现在简要说明其工作原理:

f=input;n=f();L=f()*n*n;r=[1];i=1 First we define the input() function as f 
                                   for saving bytes as we have to call it twice.
                                   Then L is defined as a list made of the 
                                   pseudorandom numbers in their order *many* times 
                                   (were *many* is an upperbound of the canges that 
                                   could be done); r as the first row and i as the row 
                                   counter.

while i<=n:print r                 A while loop that exits when the nth row has been 
                                   calculated and the printing of the actual row.

r=[L.pop(0)if r[x-1]&r[x] else r[x-1]+r[x] for x in range(1,i)];r=[1]+r+[1];i+=1
     ^           ^                 ^                         ^
     |           |                 |Same as max(r[x-1],r[x]) | from 2nd to last element
     |           | Same as min(r[x-1],r[x]) (0->False;1->True)                
     | get random bit from pseudorandom list    

这里的技巧是,我们知道位列表将始终以a开头和结尾,1因为根据规格,第一个和最后一个元素都不会被修改。这个问题。这就是声明的原因[1]+r+[1]

但是,如果r将其初始化为[1],则第一行没有任何变化,然后我们添加[1]+r+[1]第二行为[1,1,1]什么没有?

这是由于以下事实:在第一次迭代时i=1,它range(1,i)返回一个空列表,并且由于for列表中没有要进行迭代的理解,所以该结果r成为一个空列表,因此[1]+r+[1]=[1,1]。这只是在第一次迭代中发生,对我们而言是最理想的!

附注:请就如何打更多高尔夫球提出任何建议。


1
我的道歉,如果我不正确认识面临的挑战,但不能代替你min(a,b)a+b>1max(a,b)a+b?我意识到您可能必须做一些事情来处理1->的第一种情况11(我想您可以这样做L=[1]+f()...,或者找到某种在其前面插入1的方法,L因为第二行总是会弹出1)
科尔

@Cole幸运的是,不必对程序的其余部分进行任何更改,因为更改仅影响知道一对位的最小值和最大值的方式。
Ioannes 2015年

1
您错过了可以在此处删除空间的方法:r[x-1]&r[x] else:)
Kade 2015年

n ** 2-> n * n是否有效?
lirtosiast 2015年

@托马斯你是对的!
Ioannes 2015年

2

MATLAB,146 143 138

(也可以在线使用Octave,但是您需要登录以将功能保存到文件中)。

function o=c(n,L);o=zeros(n);o(:,1)=1;for i=2:n;for j=2:i;a=o(i-1,j-1);b=o(i-1,j);c=a|b;d=a&b;c(d)=L(d);L=circshift(L,-d);o(i,j)=c;end;end

该函数接受输入nL,并返回o包含输出的数组。

对于输入值,它n是一个标量,并且L是一个列向量,可以使用格式指定[;;;]。您所展示的内容不尽相同,但您说的是合理的,这似乎是灵活的。

输出格式化为n x n包含0和1的数组。

并给出一个解释:

function o=c(n,L)
%Create the initial array - an n x n square with the first column made of 1's
o=zeros(n);o(:,1)=1;
%For each row (starting with the second, as the first is done already)
for i=2:n;
    %For each column in that row, again starting with the second as the first is done
    for j=2:i;
        %Extract the current and previous elements in the row above
        a=o(i-1,j-1); %(previous)
        b=o(i-1,j);   %(current)
        %Assume that min()==0, so set c to max();
        c=a|b;
        %Now check if min()==1
        d=a&b;
        %If so, set c to L(1)
        c(d)=L(d);
        %Rotate L around only if min()==1
        L=circshift(L,-d);
        %And store c back to the output matrix
        o(i,j)=c;
    end;
end

更新:我设法优化了if-else语句,以节省一些字节。输入格式再次更改回列向量。


1

Haskell中,153个 149字节

j[_]o l=(l,o)
j(a:u@(b:c))o q@(l:m)|a*b==0=j u(o++[a+b])q|1<2=j u(o++[l])m
k(r,a)=fmap((1:).(++[1]))$j a[]r
n%l=map snd$take n$iterate k(cycle l,[1])

%返回位列表的列表。用法示例:

> 10 % [1,0,0,1] 
[[1],[1,1],[1,1,1],[1,0,0,1],[1,1,0,1,1],[1,1,1,1,1,1],[1,0,0,1,1,0,1],[1,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,0,1],[1,0,1,1,0,0,1,1,1,1]]

噢亲爱的!随便携带随机列表L是纯粹的痛苦。让我们看看这是否可以缩短。


1

C#,152个字节

这里没什么特别的。该函数返回一个2D数组,其中第一个等级是行,第二个等级是列。

缩进和换行以清楚起见:

int[,]F(int n,int[]l){
    var o=new int[n,n];
    for(int y=0,x,i=0,m;y<n;y++)
        for(o[y,x=0]=1;x++<y;)
            o[y,x]=(m=o[y-1,x-1]+o[y-1,x])<2?m:l[i++%l.Length];
    return o;
}

1

TI-BASIC,106 94 87 86 87字节

Prompt N,B
"∟B(1+remainder(𝑛,dim(∟B→u
{1
For(I,1,N
Disp Ans
augment({0},Ans)+augment(Ans,{0
Ans and Ans≠2+seq(u(𝑛-(Ans(X)<2)+2dim(∟B)),X,1,dim(Ans
End

TI-BASIC没有增量运算符,对吗?好吧,确实可以。u通常与序列一起使用的方程变量具有晦涩的特征:u使用参数调用时,该变量𝑛设置为比该参数大一个。条件增量取决于此。(我已经等了很长时间了。)

为了使列表索引正常工作,𝑛必须将其默认值设置为0,并将𝑛Min其默认设置为1,因此在运行此功能之前,请清除计算器的RAM或手动设置这些值。

augment({0},Ans)+augment(Ans,{0计算两个相邻元素之和的列表,因此它将返回0、1、2和2的列表。然后魔术就在这条线上:

Ans and Ans≠2+seq(u(𝑛-(Ans(X)≠2)+dim(∟B)),X,1,dim(Ans

Ans and                 ;set 0s to 0
Ans≠                    ;set to 0 all sums that equal...
2+
  seq(...,X,1,dim(Ans   ;execute for each element of the list
      u(                ;return this element in list of bits (looping)        
        𝑛               ;current location in the list
        -(Ans(X)≠2)+    ;subtract 1 if the element isn't 2
        2dim(∟B)        ;Add twice the dimension of the list
                           ;(because n<nMin on the first iteration, it's out of the domain
                           ;this prevents an error)
       )                      ;set n to one greater than that value
                              ;i.e. increment if element≠2
                        ;Will equal Ans(X) iff Ans(X)=2 and the bit read false

这行的结果是,如果列表元素为0或如果列表元素为2且读取的位为0,则列表元素为0。

Result of above line
n \ u |  0  |  1
0        0     0

测试用例:

N=?7
B=?{0,1,0
             {1}
           {1 1}
         {1 0 1}
       {1 1 1 1}
     {1 1 0 0 1}
   {1 1 1 0 1 1}
 {1 0 0 1 1 1 1}
            Done
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.