擬似ランダムセルラーオートマトン


14

前書き

この課題では、非常に悪い擬似乱数を使用して、特定の確率的セルオートマトンをシミュレートします。セルオートマトンは、次のローカルルールによってバイナリ文字列で定義されます。セルの左隣とセル自体に状態aとがあると仮定しbます。

  • の場合min(a,b) == 0、新しい状態はbですmax(a,b)
  • の場合min(a,b) == 1、の新しい状態がbからランダムに選択され{0,1}ます。

次の図は、単一のの可能な10段階の進化を示しています1

1
11
101
1111
11001
101011
1111111
10001001
110011011
1010111101

隣接する2つ1のsが時々に1、そして時にはに進化し、0最も境界のビットが常に1sであることに注意してください。あなたの仕事は、この形式のセルオートマトンの進化を生み出すことです。

インプット

入力は、n表示する行数を示す正の整数と、Lランダム性のソースとして使用する空でないビットのリストです。

出力

出力は、リストのリストまたはビットの2D配列であり、上の図のように、時間ステップ1に対する単一の進化をn表します。0必要に応じて、出力にsを埋め込み、同じ長さの行を取得できますが、先頭に0s があってはなりません。

セルオートマトンのランダムな選択は、リストから引き出され、L使い果たされたときに最初に戻ります。より明確に、出力が上から下、左から右の形式で一度に1行を横断する場合、連続するランダムな選択はL、必要な回数だけ繰り返されるリストを形成するものとします。

入力がn = 7とであるとしL = [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。これはL2.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

回答:


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>

where <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]>1たのr[x-1]&r[x]はビット演算子で、最小値は(r[x-1],r[x])

@ThomasKwaに1バイト節約するn*n代わりに提案してくれてありがとうn**2

-1バイトをありがとう@Shebang

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

-7バイトの@Coleに感謝します。

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

@ジャクベの答えにさえ近いわけではありませんが、コーディングとゴルフを楽しんでいます。

2つの入力が必要です。最初の入力は行数で、2番目の入力は擬似乱数ソースリストです。コンソールに1行ずつ、それぞれ新しい行に印刷します。

例として:

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    

ここでのコツは1、最初と最後の要素が仕様により変更されないため、ビットリストは常にaで始まり、aで終わることを知っていることです。質問の。それが声明の理由です[1]+r+[1]

rがとして初期化されている場合[1]、最初の行に変更はなく[1]+r+[1]、2番目の行がそうでない理由を追加します[1,1,1]か?

これは、最初の反復であることに起因しているi=1ので、range(1,i)空のリストと、その結果としてリターンfor反復処理するためには何も持っていないリストの内包ではrとても空のリストになります[1]+r+[1]=[1,1]。これは、私たちにとって理想的な最初の反復で発生します!

PS:もっとゴルフをする方法については、お気軽にご提案ください。


1
私の謝罪は、私が正しく挑戦を理解していない場合は、しかし、あなたは置き換えることができないmin(a,b)a+b>1し、max(a,b)a+b?おそらく、最初のケースを処理するために何かをする必要があると思います1-> 11(できると思いますL=[1]+f()...。またはL、2番目の行で常に1をポップするため、1を前に挿入する方法を見つけます)
cole

@Cole幸運なことに、変更はビットのペアの最小値と最大値を知る方法にのみ影響するため、プログラムの残りの部分に変更を加える必要はありません。
イオアンズ

1
あなたがここにスペースを削除することを逃した:r[x-1]&r[x] else:)
カーデ

n ** 2-> n * nは機能しますか?
リトシアスト

@トーマスあなたは正しいです!
イオアンズ

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

関数は入力nとを受け取り、出力を含むL配列oを返します。

入力値の場合、nはスカラーLで、フォーマットで指定できる列ベクトルです[;;;]。あなたが示すものではありませんが、理にかなった範囲内で柔軟であるとあなたは言います、そして、これはそうです。

出力は、n x n0と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バイト

ここには特別なものはありません。この関数は、最初のランクが行で、2番目のランクが列である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があります。引数で呼び出されると、変数𝑛はその引数よりも1つ大きい値に設定されます。条件付き増分はこれに依存します。(私は長い間それを使用するのを待っていました。)

リストのインデックス作成が適切に機能するに𝑛は、デフォルト値の0であり𝑛Min、デフォルトの1である必要があるため、これを実行する前に計算機のRAMをクリアするか、これらの値を手動で設定します。

augment({0},Ans)+augment(Ans,{0隣接する2つの要素の合計のリストを計算するため、0、1、および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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.