Pseudorandom Cellular Automaton


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

สังเกตว่า1บางครั้ง s สองอันที่อยู่ติดกันพัฒนาไป1มาและบางครั้งถึง0และบิตที่ขอบสุดจะเป็น1s เสมอ งานของคุณคือผลิตวิวัฒนาการออโตมาตาเซลในรูปแบบนี้

ปัจจัยการผลิต

อินพุตของคุณเป็นจำนวนเต็มบวกnแสดงถึงจำนวนแถวที่จะแสดงและรายการบิตที่ไม่ว่างLซึ่งเราใช้เป็นแหล่งของการสุ่ม

เอาท์พุต

การส่งออกของคุณคือรายชื่อของรายการหรืออาร์เรย์ 2 มิติของบิตภาพวาดวิวัฒนาการของเดียว1สำหรับnขั้นตอนเวลาในรูปดังกล่าวข้างต้น คุณสามารถวางผลลัพธ์ด้วย0s เพื่อให้ได้แถวที่มีความยาวเท่ากันหากต้องการ แต่จะต้องไม่มีการนำหน้า0s

ตัวเลือกแบบสุ่มในหุ่นยนต์เซลลูล่าร์จะต้องดึงออกมาจากรายการLแล้วกระโดดกลับไปที่จุดเริ่มต้นเมื่อหมดแล้ว อย่างชัดเจนยิ่งขึ้นถ้าผลลัพธ์ถูกส่งผ่านหนึ่งแถวในรูปแบบเวลาจากบนลงล่างจากซ้ายไปขวาจากนั้นตัวเลือกสุ่มที่ต่อเนื่องจะสร้างรายการ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ซึ่ง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

รุ่น Pseudorandom:

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>

โดยที่<empty>บ่งชี้ว่ามีบรรทัดว่างต่อท้าย แต่ละบรรทัดไปในไฟล์แยกต่างหากและ#ควรแทนที่ด้วย linefeeds (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 สำหรับการแนะนำ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    

เคล็ดลับที่นี่คือเรารู้ว่ารายการบิตมักจะเริ่มต้นและจบด้วย1เพราะองค์ประกอบแรกและสุดท้ายจะไม่เคยแก้ไขเนื่องจากข้อกำหนด ของคำถาม [1]+r+[1]นั่นเป็นเหตุผลที่คำสั่ง

แต่ถ้าได้rรับการเริ่มต้นเนื่องจาก[1]ไม่มีการเปลี่ยนแปลงในแถวแรกแล้วเราจะเพิ่ม[1]+r+[1]แถวที่สองมา[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()...หรือหาวิธีแทรก 1 ข้างหน้าLเพราะมันจะโผล่ 1 สำหรับบรรทัดที่สองเสมอ)
cole

@Cole โชคดีที่ไม่มีการเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นกับโปรแกรมส่วนที่เหลือเนื่องจากการเปลี่ยนแปลงจะส่งผลต่อวิธีการรู้ค่า min และค่าสูงสุดของคู่บิต
Ioannes

1
คุณพลาดที่จะลบช่องว่างที่นี่: r[x-1]&r[x] else:)
Kade

n ** 2 -> n * n จะใช้ได้ไหม
lirtosiast

@ โทมัสคุณพูดถูก!
Ioannes

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 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คำนวณรายการผลรวมขององค์ประกอบสองรายการที่อยู่ติดกันดังนั้นมันจะส่งกลับรายการ 0s, 1s และ 2s จากนั้นเวทมนตร์ก็อยู่ในบรรทัดนี้:

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 ถ้าพวกเขาเป็น 0 หรือถ้าพวกเขาเป็น 2 และการอ่านบิตเป็น 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.