สร้างกองทราย


59

sandpile คริสต์สำหรับวัตถุประสงค์ของเราคือตารางอนันต์กับจำนวนเต็มพิกัดต้นที่ว่างเปล่าของทราย หลังจากนั้นทุกวินาทีเม็ดทรายจะถูกวางที่ (0,0) เมื่อใดก็ตามที่เซลล์กริดมีเม็ดทราย 4 เม็ดขึ้นไปมันจะกระจายเม็ดทรายหนึ่งเม็ดไปยังเพื่อนบ้านทั้งสี่ในเวลาเดียวกัน เพื่อนบ้านของ (x, y) คือ (x-1, y), (x + 1, y), (x, y-1) และ (x, y + 1)

เมื่อเซลล์หกมันอาจทำให้เพื่อนบ้านรั่วไหล ข้อเท็จจริงบางอย่าง:

  • น้ำตกนี้จะหยุดในที่สุด
  • ลำดับการรั่วไหลของเซลล์ที่ไม่เกี่ยวข้อง ผลลัพธ์จะเหมือนกัน

ตัวอย่าง

หลังจาก 3 วินาทีกริดดูเหมือนว่า

.....
.....
..3..
.....
.....

หลังจาก 4 วินาที:

.....
..1..
.1.1.
..1..
.....

หลังจาก 15 วินาที:

.....
..3..
.333.
..3..
.....

และหลังจาก 16 วินาที:

..1..
.212.
11.11
.212.
..1..

ความท้าทาย

ในสองสามไบต์ให้ได้มากที่สุดให้เขียนฟังก์ชันที่ใช้จำนวนเต็มบวกtและส่งออกรูปภาพของ sandpile หลังจากtวินาที

อินพุต

จำนวนเต็มบวกเดียวtในรูปแบบที่คุณเลือก

เอาท์พุต

รูปภาพของ sandpile หลังจากtวินาทีโดยใช้อักขระ

 . 1 2 3

แก้ไข: ใช้อักขระสี่ตัวที่คุณต้องการหรือวาดภาพ หากคุณไม่ได้ใช้ ".123" หรือ "0123" ให้ระบุคำตอบในสิ่งที่ตัวละครมีความหมาย

ซึ่งแตกต่างจากตัวอย่างผลลัพธ์ของคุณควรมีจำนวนแถวและคอลัมน์น้อยที่สุดที่จำเป็นในการแสดงส่วนที่ไม่ใช่ศูนย์ของทราย

นั่นคือสำหรับอินพุต 3 เอาต์พุตควรเป็น

 3

สำหรับ 4 เอาต์พุตควรเป็น

 .1.
 1.1
 .1.

เกณฑ์การให้คะแนน

คะแนนกอล์ฟมาตรฐานใช้

กฎระเบียบ

ไม่มีฟังก์ชั่นหรือไลบรารีภาษาที่รู้อยู่แล้วว่ามีทรายแบบใดบ้างที่ได้รับอนุญาต

แก้ไข: ส่วนเอาท์พุทได้รับการแก้ไขข้อ จำกัด ชุดตัวละครได้รับการยกอย่างสมบูรณ์ ใช้อักขระหรือสีสี่ตัวที่คุณต้องการ


2
การป้อนข้อมูลที่สามารถทีจะเป็น0? ouput คืออะไร?
Luis Mendo

1
ถูกต้องหรือไม่สำหรับการประทับเวลาที่กำหนดให้มีหลายหลากสามารถเกิดขึ้นในแถว? ดังนั้นในเวลานั้นน้ำตกจึงเกิดขึ้นเรื่อย ๆ จนกว่าทุกเซลล์จะมีค่าอีก 3 หรือน้อยกว่านั้น?
ข้อบกพร่อง

2
@flawr: ใช่ว่าจะถูกต้อง ดูความแตกต่างระหว่าง t = 15 และ t = 16
El'endia Starman

@LuisMendo อินพุตถูกระบุว่าเป็นบวกtดังนั้นศูนย์จึงไม่ใช่อินพุตที่ถูกต้อง
Eric Tressler

1
มันจำเป็นจริงๆ.หรือเปล่าที่จะต้องมีเซลล์ว่างเปล่า? เราสามารถมี0เซลล์ว่างที่ใช้ได้หรือไม่?
Andreï Kostyrka

คำตอบ:


56

R, 378 343 297 291 ไบต์

ตามปกติผู้ใช้ป้อนข้อมูลของเขา / เธอผ่านscan()(ฉันได้ใช้ตัวแปรtแล้วให้เราใช้zแทน) ดังนั้นบรรทัดที่สองควรเปิดตัวแยกต่างหากจากนั้นส่วนที่เหลือ:

e=numeric
a=1%*%scan()
x=1
o=a>3
n=1
while(any(o)){
v=which(o,T)
if(any(v==1)){a=rbind(e(n+2),cbind(e(n),a,e(n)),e(n+2));x=x+1;n=n+2;v=which(a>3,T)}
q=nrow(v)
u=cbind(e(q),1)
l=v-u[,1:2];r=v+u[,1:2];t=v-u[,2:1];b=v+u[,2:1]
a[l]=a[l]+1;a[r]=a[r]+1;a[t]=a[t]+1;a[b]=a[b]+1
a[v]=a[v]-4
o=a>3}
a

เอาต์พุตอาร์เรย์ที่มีค่าaat at tgeneration (0, 1, 2 หรือ 3)

กรณีทดสอบ:

z=3
     [,1]
[1,]    3
z=4
     [,1] [,2] [,3]
[1,]    0    1    0
[2,]    1    0    1
[3,]    0    1    0
z=16
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    1    0    0
[2,]    0    2    1    2    0
[3,]    1    1    0    1    1
[4,]    0    2    1    2    0
[5,]    0    0    1    0    0

ช่วยเราว่าสิ่งนี้สมมาตรทั้งในแนวตั้งและแนวนอนซึ่งหมายความว่าเป็นจุดซ้ายสุดที่มีความสูง 4 ซึ่งหมายความว่าจุดสูงสุด, ขวาสุดและต่ำสุดก็คือ 4

โอ้และฉันก็บอกว่าคุณสามารถสร้างภาพที่สวยงามได้หรือไม่?

หลังจาก 1,000 หยด:

Abelian sandpile หลังจาก 1,000 ขั้นตอน

หลังจาก 50,000 ลดลง (≈4วินาที):

Abelian sandpile หลังจาก 50,000 ขั้นตอน

หลังจาก 333333 ลดลง (≈15นาที):

Abelian sandpile หลังจากผ่านไป 100,000 ขั้นตอน

คุณสามารถวาดมันได้เช่นกัน!

image(1:n,1:n,a,col=colorRampPalette(c("#FFFFFF","#000000"))(4), axes=F, xlab="", ylab="")

สิ่งนี้ใช้เวลา 4 วินาทีสำหรับการทำซ้ำ 10,000 ครั้ง แต่ช้าลงอย่างมากสำหรับขนาดอาร์เรย์ที่ใหญ่กว่า (เช่นสองสามนาทีสำหรับการทำซ้ำ 100,000 ครั้ง) นี่คือเหตุผลที่มันช้ามาก (ฉันประเมินอัตราการเติบโตดังที่อัตราการเจริญเติบโตได้รับτ (i) ≈689· i ^ 1.08 ดังนั้นเวลาเฉลี่ยต่อหนึ่งเม็ดเพิ่มเติมจนกระทั่งเม็ดทรายทั้งคู่ตกลงหลังจากiขั้นตอนที่ใหญ่กว่าเล็กน้อย) และเวลาทั้งหมดในการทำงานของจำนวนเมล็ดเติบโตช้ากว่าสมการกำลังสองเล็กน้อย (T (i) ≈0.028 * i ^ 1.74):

เฉลี่ยซ้ำจนกระทั่งกองทรุด

เวลาการคำนวณโดยประมาณ

และตอนนี้พร้อมคำอธิบายที่สมบูรณ์:

e=numeric # Convenient abbreviation for further repeated use
a=1%*%scan() # Creates a 1×1 array with a user-supplied number
x=1 # The coordinate of the centre
o=a>3 # Remember which cells were overflown
n=1 # Array height that is going to change over time
while(any(o)){ # If there is still any overflow
  v=which(o,T) # Get overflown cells' indices
  if(any(v==1)){ # If overflow occurred at the border, grow the array
    a=rbind(e(n+2),cbind(e(n),a,e(n)),e(n+2)) # Growing
    x=x+1 # Move the centre
    n=n+2 # Change the height
    v=which(a>3,T) # Re-index the overflowed cells
    }
  q=nrow(v) # See how many indices are overflown
  u=cbind(e(q),1) # Building block for neighbours' indices
  l=v-u[,1:2];r=v+u[,1:2];t=v-u[,2:1];b=v+u[,2:1] # L, R, T, B neighbours
  a[l]=a[l]+1;a[r]=a[r]+1;a[t]=a[t]+1;a[b]=a[b]+1 # Increment neighbours
  a[v]=a[v]-4 # Remove 4 grains from the overflown indices
  o=a>3} # See if still overflown indices remain
a # Output the matrix

นี่เป็นครั้งแรกในชีวิตของฉันเมื่อการเติบโตของวัตถุ (เช่นa <- c(a, 1)) ทำงานเร็วกว่าการจัดสรรเมทริกซ์ที่ว่างเปล่าขนาดใหญ่ไว้ล่วงหน้าสำหรับค่าและเติมมันทีละน้อยโดยไม่ต้องใช้ศูนย์จำนวนหนึ่ง

ปรับปรุง แข็งแรงเล่นกอล์ฟ 18 ไบต์โดยการลบarr.indในwhichเนื่องจากBillywobและแทนที่rep(0,n)ด้วยe=numeric;e(n)ใน 5 กรณีเนื่องจากJDLและ 17 ไบต์เนื่องจากJDL

อัปเดต 2.เนื่องจาก sandpile เป็น Abelian มันอาจเริ่มต้นด้วยความสูงที่ต้องการดังนั้นฉันจึงลบลูปที่ซ้ำซ้อนและเพิ่มประสิทธิภาพมากขึ้น!


1
ฉันได้คะแนนของคุณเกี่ยวกับคอลัมน์พิเศษ, ดัชนีแถวที่คุณกำลังส่งออก แต่ฉันคิดว่าฉันต้องการ จำกัด ผลลัพธ์ให้เป็นเพียงแค่ "คำตอบ" และไม่มีอะไรเพิ่มเติม ฉันดีใจที่คุณรวมรูปภาพด้วย
Eric Tressler

1
คำตอบที่ดีAndreï! คุณสามารถเล่นกอล์ฟได้สองสามไบต์ตัวอย่างเช่นการกำหนดค่าล่วงหน้าrep()เนื่องจากคุณใช้งานได้ 6 ครั้ง ประการที่สองฉันไม่คิดว่าคุณจะต้องเขียนarr.ind=Tตัวเลือกสำหรับwhich()ฟังก์ชั่น which(...,T)เพียงแค่ใช้
Billywob

1
มันอาจจะเป็น golfier เพื่อกำหนดn=numericและใช้แทนเนื่องจากเป็นตัวละครน้อยกว่าn(k) r(0,k)ฉันชอบรูปที่
JDL

1
ข้อเสนอแนะอื่น ๆ : เป็นตัวละครน้อยกว่า1%*%0 array(0,c(1,1))อาร์กิวเมนต์ที่สองที่u <- cbindสามารถเป็น 1 cbindจะขยายไปจนถึงความยาวของอาร์กิวเมนต์แรกโดยค่าเริ่มต้น
JDL

1
@GregMartin แก้ไขสิ่งนี้ ขอโทษสำหรับสิ่งนั้น; ในภาษาแรกของฉันเราใช้คำว่า "ตัวตน" และไม่เคยสนใจเรื่องเพศของคนที่สงสัย (เช่น "ก้าวเล็ก ๆ สำหรับผู้ชายคนหนึ่ง"); ยังคงเป็นบางครั้งในโอกาสที่หายากมากที่ผมเรียกสุนัข“เธอ” หรือ“เขา” ในขณะที่มันควรจะเป็น“มัน” เว้นแต่เหมือนคุณเป็นเจ้าของและคุณจริงๆอยากจะเน้นเพศของ anumal ของคุณ ( ทั้งๆที่ความจริงที่ว่าการบอกผู้ชายจากผู้หญิงนั้นไม่ยากเลย)
Andreï Kostyrka

13

MATL , 55 53 48 43 42 ไบต์

แรงบันดาลใจจากคำตอบของ @ flawr

เอาท์พุทแบบกราฟิก :

0i:"Gto~+XytP*+t"t4=t1Y6Z+b+w~*]]tat3$)1YG

ลองที่ MATL Online! . มันต้องใช้เวลาประมาณ 10 30วินาทีสำหรับการป้อนข้อมูล คุณอาจต้องรีเฟรชหน้าและกด "Run" อีกครั้งหากไม่ได้ผล

นี่คือตัวอย่างผลลัพธ์สำหรับการป้อนข้อมูล100:

ป้อนคำอธิบายรูปภาพที่นี่

เอาต์พุต ASCII (43 ไบต์) :

0i:"Gto~+XytP*+t"t4=t1Y6Z+b+w~*]]tat3$)48+c

ลองออนไลน์!

คำอธิบาย

0          % Push a 0. This is the initial array. Will be resized in first iteration
i:         % Take input n. Generate range [1 2 ... n]
"          % For each, i.e. repeat n times
  Gto~+    %   Push input and add negate parity. This "rounds up" n to odd number
           %   m = n or n+1
  Xy       %   Identity matrix with that size
  tP*      %   Multiply element-wise by vertically flipped copy. This produces a
           %   matrix with a 1 in the center and the rest entries equal to 0
  +        %   Add to previous array. This updates the sandpile array
  t        %   Duplicate
  "        %   For each column (i.e. repeat m times)
    t4=    %     Duplicate. Compare with 4 element-wise. This gives a 2D mask that
           %     contains 1 for entries of the sandpile array that equal 4, and 0
           %     for the rest
    t      %     Duplicate
    1Y6    %     Predefined literal: [0 1 0; 1 0 1; 0 1 0]
    Z+     %     2D convolution, maintaining size
    b      %     Bubble up to bring sandpile array to top
    +      %     Element-wise addition. This adds 1 to the neighbours of a 4
    w      %     Swap to bring copy of mask to top
    ~*     %     Multiply bu negated mask. This removes all previous 4
  ]        %  End
]          % End
t          % Duplicate the updated sandpile array
a          % 1D mask that contains 1 for columns that contain a 1. This will be
           % used as a logical index to select columns
t          % Duplicate. This will be used as logical index to select rows (this
           % can be done because of symmetry)
3$)        % Keep only those rows and columns. This trims the outer zeros in the
           % sandpile array
1YG        % Display as scaled image

3
1Y6ฉันอิจฉา
ข้อบกพร่อง

1
@flawr แต่คุณ~mod(spiral(3),2)เป็น :-) มากฉลาดมากขึ้น
หลุยส์ Mendo

11

Matlab, 160 156 148 bytes

n=input('');z=zeros(3*n);z(n+1,n+1)=n;for k=1:n;x=z>3;z=z+conv2(+x,1-mod(spiral(3),2),'s');z(x)=z(x)-4;end;v=find(sum(z));z=z(v,v);[z+48-(z<1)*2,'']

วิธีแรกคือสร้างเมทริกซ์ที่ใหญ่เกินไปโดยมีnจุดกึ่งกลางอยู่ตรงนั้น จากนั้นการคำนวณแบบเรียงซ้อนจะทำให้เกิดการบิดแบบ 2d ที่สะดวกมาก ในตอนท้ายส่วนเกินจะถูกตัดออกและสิ่งทั้งหมดจะถูกแปลงเป็นสตริง

ตัวอย่างผลลัพธ์สำหรับ t=100

...121...
..32.23..
.3.323.3.
123.3.321
2.23.32.2
123.3.321
.3.323.3.
..32.23..
...121...

เหมือนเคย:

Convolution คือกุญแจสู่ความสำเร็จ


v=any(z)แทนv=find(sum(z))(ฉันใช้คำตอบนั้น) นอกจากนี้2*~zแทน(z<1)*2
Luis Mendo

คอมพิวเตอร์ของฉันค้างที่อินพุตn=500... มันได้รับการประมวลผลn=400เป็นเวลาหลายวินาที ฉันกำลังทำอะไรผิดหรือเปล่า?
Andreï Kostyrka

@ AndreïKostyrkaมันใช้งานได้สำหรับฉัน (Matlab R2015b)
Luis Mendo

1
@ AndreïKostyrkaสำหรับอินพุตของnโปรแกรมนี้จะสร้าง3*n x 3*nเมทริกซ์ดังนั้นมันจึงจำเป็นต้องเก็บข้อมูลเกี่ยวกับ9*n^2ตัวเลข นอกจากนี้ยังไม่มีประสิทธิภาพโดยสิ้นเชิงเนื่องจากเรามีการทำซ้ำที่ไม่จำเป็นโดยสิ้นเชิงตั้งแต่ 1 จนถึง n แต่แล้วอีกครั้งนี้เป็นรหัสกอล์ฟทำให้โปรแกรมที่มีประสิทธิภาพเป็นถ้วยชาที่แตกต่างกัน
ข้อบกพร่อง

@ AndreïKostyrkaคุณสามารถ makie มันหน่วยความจำมีประสิทธิภาพมากขึ้นโดยใช้เมทริกซ์เบาบาง (บรรทัดที่สอง: z=sparse(zeros(2*n+1))) while any(z(:)>3)และการเปลี่ยนแปลงสำหรับวง จากนั้นคุณสามารถคำนวณเคอร์เนล convolution เพียงครั้งเดียว: kern = 1-mod(spiral(3),2).
ข้อบกพร่อง

9

Python 2, 195 +1 +24 = 220 217

from pylab import*
ifrom scipy.signal import convolve2d as c
k=(arange(9)%2).reshape(3,3)
def f(n):g=zeros((n,n),int);g[n/2,n/2]=n;exec"g=c(g/4,k,'same')+g%4;"*n;return g[any(g,0)].T[any(g,0)]

เอาต์พุตสำหรับ n = 16

array([[0, 0, 1, 0, 0],
       [0, 2, 1, 2, 0],
       [1, 1, 0, 1, 1],
       [0, 2, 1, 2, 0],
       [0, 0, 1, 0, 0]])

มีช่องว่างและการวนซ้ำที่ไม่จำเป็นจำนวนมากโดยใช้nเป็นขอบเขตบน "ดีพอ" แต่ n = 200 ยังคงแล้วเสร็จในหนึ่งวินาทีและ n = 500 ในเวลาประมาณ 12 วินาที

ungolfed

from pylab import*
from scipy.signal import convolve2d as c
k=array([0,1,0],
        [1,0,1],
        [0,1,0])
def f(n):
  g=zeros((n,n))                 # big grid of zeros, way bigger than necessary
  g[n/2,n/2]=n                   # put n grains in the middle
  exec"g=c(g/4,k,'same')+g%4;"*n # leave places with <4 grains as is, convolve the rest with the kernel k, repeat until convergence (and then some more)
  return g[any(g,0)].T[any(g,0)] # removes surrounding 0-rows and columns

แทนที่return xด้วยการimshow(x)เพิ่มตัวละครตัวหนึ่งและเอาท์พุทภาพสอดแทรกน่าเกลียดเพิ่มการimshow(x,'gray',None,1,'nearest')ลบการแก้ไขพร่ามัวนำเอาท์พุทได้ถึงรายละเอียด

n = 100


ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อฉันเรียกใช้รหัสของคุณ: ImportError: No module named convolve2d. การเปลี่ยนimport scipy.signal.convolve2d as cเพื่อfrom scipy.signal import convolve2d as cแก้ไขปัญหา ฉันใช้ scipy เวอร์ชั่น 0.16.1 ฉันต้องใช้เวอร์ชั่นที่เก่ากว่าหรือใหม่กว่าหรือไม่ หรือเป็นปัญหาอย่างอื่น?
Andrew Epstein

แปลกแล้วตอนนี้คุณพูดถึงว่ามันไม่ได้ผลสำหรับฉันอีกต่อไปเช่นกัน ฉันอาจทำให้ถูกต้องเป็นครั้งแรกในโหมดโต้ตอบจากนั้นจึงย่อให้สั้นลงและละเว้นข้อผิดพลาด แต่ฟังก์ชันอยู่ในหน่วยความจำ
DenDenDo

6

Perl, 157 147 ไบต์

รวม +1 สำหรับ -p

ทำงานด้วยการนับบน STDIN พิมพ์แผนที่โดยใช้0123ไปที่ STDOUT:

sandpile.pl <<< 16

sandpile.pl:

#!/usr/bin/perl -p
map{++substr$_,y///c/2-1,1;/4
/?$.+=s%^|\z%0 x$..$/%eg+!s/\b/0/g:s^.^$&%4+grep{3<substr$\,0|$_+"@+",1}-$.-2,-2,0,$.^eg while/[4-7]/}($\="0
")x$_}{

5

Python 3 2, 418 385 362 342 330 ไบต์

w='[(i,j)for i in r(n)for j in r(n)if a[i][j]>3]'
def f(z):
 a,x,r=[[z]],0,range
 for _ in[0]*z:
  n=len(a);v=eval(w)
  if[1for b,c in v if(b==0)+(c==0)]:n+=2;a=[[0]*n]+[[0]+a[i]+[0]for i in r(n-2)]+[[0]*n];x+=1;v=eval(w)
  for c,d in v:exec'a[c+%s][d+%s]+=1;'*4%(-1,0,1,0,0,-1,0,1);a[c][d]-=4
 for i in a:print''.join(map(str,i))

แก้ไข: บันทึก 6 ไบต์ด้วย @ Qwerp-Derp

เครดิตทั้งหมดให้กับ @ Andreï Kostyrka เนื่องจากนี่เป็นการแปลโดยตรงของรหัส R ของเขาเป็น Python


ฉันคิดว่าคุณสามารถย้ายการมอบหมายa,x,rไปยังอาร์กิวเมนต์ของฟังก์ชันได้
Loovjo

1
ฉันตีกอล์ฟโค้ดของคุณไม่กี่ไบต์ ... มันไม่มาก แต่ก็ต้องทำ คุณรังเกียจไหมถ้าฉันแก้ไขคำตอบของคุณและถ้าฉันเปลี่ยนเวอร์ชั่นของ Python เป็น Python 2
clismique

@ Qwerp-Derp: อย่าลังเล! ฉันชอบที่จะเห็นสิ่งที่คุณทำ
Andrew Epstein

3

JavaScript, 418 416 406 400 393 ไบต์

สร้างฟังก์ชั่นที่ไม่ระบุชื่อที่แสดงผลลัพธ์บนคอนโซล

var f =
    t=>{a=(q,w)=>Math.max(q,w);c=_=>{x=a(p[0],x);y=a(p[1],y);m[p]=(g(p)+1)%4;if(!m[p]){s.push([p[0],p[1]]);}};x=y=0,m={};g=k=>{v=m[k];return!v?0:v;};m[o=[0,0]]=1;s=[];while(--t){m[o]=(m[o]+1)%4;if(!m[o]){s.push(o);}while(s.length){p=s.pop();p[0]++;c();p[0]-=2;c();p[0]++;p[1]++;c();p[1]-=2;c();p[1]++;}}s='';for(i=-x;i<=x;i++){for(j=-y;j<=y;j++){v=g([i,j]);s+=v==0?'.':v;}s+='\n';}console.log(s);}
<input id="i" type="number"><input type="button" value="Run" onclick="var v = +document.getElementById('i').value; if (v>0) f(v)">


1
คำเตือน: ฉันกด 'เรียกใช้' โดยไม่ป้อนข้อมูลและหน้าจอของฉันขัดข้อง (วนซ้ำไม่สิ้นสุด) อย่าโง่อย่างที่ฉันเป็น
roberrrt-s

1
@Roberrrt ฉันได้อัพเดตคำตอบเพื่อป้องกันสิ่งนี้
hetzi

3

Nim, 294 ตัวอักษร

import os,math,sequtils,strutils
var
 z=parseFloat paramStr 1
 y=z.sqrt.toInt+1
 w=y/%2
 b=y.newSeqWith newSeq[int] y
 x=0
proc d(r,c:int)=
 b[r][c]+=1;if b[r][c]>3:b[r][c]=0;d r-1,c;d r,c+1;d r+1,c;d r,c-1
for i in 1..z.toInt:d w,w
while b[w][x]<1:x+=1
for r in b[x..< ^x]:echo join r[x..< ^x]

รวบรวมและเรียกใช้:

nim c -r sandbox.nim 1000

หมายเหตุ:

  1. ฉันสามารถสร้างเวอร์ชันที่สั้นกว่าซึ่งใช้ขนาดตารางคงที่ แต่ฉันแก้ไขได้ตามความต้องการของไดนามิก
  2. เมื่อคำนวณ sandbox แล้วxจะคำนวณเป็นจำนวนคอลัมน์ศูนย์ที่เริ่มต้นของแถวกลาง
  3. สำหรับการแสดงผลตารางจะถูกแบ่งย่อยลงโดยไม่รวมxแถวและคอลัมน์จากปลายแต่ละด้าน

ประสิทธิภาพ

nim c --stackTrace:off --lineTrace:off --threads:off \ 
      --checks:off --opt:speed sandbox.nim

time ./sandbox   10000       0.053s
time ./sandbox   20000       0.172s
time ./sandbox   30000       0.392s
time ./sandbox   40000       0.670s
time ./sandbox  100000       4.421s
time ./sandbox 1000000    6m59.047s

3

สกาลา 274 ไบต์

val t=args(0).toInt
val s=(Math.sqrt(t)+1).toInt
val (a,c)=(Array.ofDim[Int](s,s),s/2)
(1 to t).map{_=> ?(c,c)}
println(a.map{_.mkString}.mkString("\n"))
def?(b:Int,c:Int):Unit={
a(b)(c)+=1
if(a(b)(c)<4)return
a(b)(c)=0
?(b+1,c)
?(b-1,c)
?(b,c+1)
?(b,c-1)
}

การใช้งาน:

scala sandpile.scala <iterations>

ฉันไม่คิดว่ามีอะไรมากมายที่จะอธิบายเกี่ยวกับสิ่งนี้ โดยพื้นฐานแล้วมันจะเพิ่มเม็ดทรายหนึ่งเม็ดลงไปตรงกลาง จากนั้นตรวจสอบว่ามันมีขนาดใหญ่กว่า 4 หรือไม่ถ้าเป็นเช่นนั้นมันจะหกและตรวจสอบเพื่อนบ้านทั้งหมดที่มีขนาดใหญ่กว่า 4, หกล้นเป็นต้นมันค่อนข้างเร็ว

ประสิทธิภาพ:

  • t = 10000 72ms
  • t = 20,000 20,000
  • t = 30000 419ms
  • t = 40000 659ms
  • t = 100000 3413ms
  • t = 1000000 ประมาณ 6 นาที

โปรแกรมของฉันแสดงให้เห็นว่าโดยมีศูนย์กลางอยู่ที่ (0,0) ทรายนั้นจะมีรัศมีถึง 15 ที่ t = 1552 ที่จะต้องมีอาร์เรย์ 31x31 ในการจัดเก็บ (พิกัด -15 ถึง 15 รวม) คุณแน่ใจว่าสิ่งนี้ถูกต้องผ่าน t = 5000 หรือไม่
Eric Tressler

ฉันไม่แน่ใจว่าสิ่งนี้ถูกต้อง แต่ฉันคิดว่าฉันมีเหตุผลที่ถูกต้อง? ฉันได้รับดัชนีอาเรย์นอกขอบเขตยกเว้นใน t> 5593
AmazingDreams

เมื่อฉันเพิ่มขึ้นจากนั้นตรวจสอบทันทีว่ามีการรั่วไหลมันจะไปนอกขอบเขตที่ t = 1552 ฉันจะบอกว่านั่นคือการดำเนินการที่ถูกต้อง ฉันอัปเดตรหัสแล้ว
AmazingDreams

ประสิทธิภาพการทำงานของคุณสามารถเอาชนะได้โดยการจัดการอาเรย์โดยตรงใน C หรือ Fortran ด้วยการเพิ่มประสิทธิภาพคอมไพเลอร์ ฉันอิจฉาคุณ.
Andreï Kostyrka

@ AndreïKostyrkaใช่นี่คือที่ส่องประกาย! เอาท์พุทของฉันไม่เป็นไปตามข้อกำหนด แต่ฉันต้องทำงานต่อไป
AmazingDreams

2

J, 76 ไบต์

p=:0,.~0,.0,~0,]
p`(4&|+3 3([:+/@,*&(_3]\2|i.9));._3[:<.4%~p)@.([:*/4>{.)^:_

ฉันกำหนดคำกริยาpที่เป็นแผ่นซึ่งเป็นเส้นขอบของศูนย์รอบอินพุต กริยาหลักใช้อาเรย์เป็นอินพุต จากนั้นจะตรวจสอบแถวแรกสำหรับกองทรายที่มี 4 เม็ดขึ้นไป หากมีการทำเช่นนั้นมันจะส่งออกอาร์เรย์เดียวกันยกเว้นการใช้เบาะpและมิฉะนั้นจะทำการแปลง 2d เพื่อจำลองการตกของเมล็ด ^:_คำกริยาหลักซ้ำแล้วซ้ำอีกจนบรรจบกันใช้อำนาจในการดำเนินการ

การใช้

   p =: 0,.~0,.0,~0,]
   f =: p`(4&|+3 3([:+/@,*&(_3]\2|i.9));._3[:<.4%~p)@.([:*/4>{.)^:_
   f 15
0 3 0
3 3 3
0 3 0
   f 50
0 0 0 1 0 0 0
0 0 3 1 3 0 0
0 3 2 2 2 3 0
1 1 2 2 2 1 1
0 3 2 2 2 3 0
0 0 3 1 3 0 0
0 0 0 1 0 0 0
   timex 'r =: f 50000'
46.3472
   load 'viewmat'
   ((256#.3&#)"0<.255*4%~i._4) viewmat r

ใช้เวลาประมาณ 46 วินาทีในการคำนวณผลลัพธ์สำหรับn = 50,000 และผลลัพธ์สามารถแสดงได้โดยใช้viewmataddon ที่มีรูปแบบสีขาวดำ

รูป


2

C 229 (มีคำเตือนมากมาย)

G[99][99],x,y,a=99,b=99,c,d;S(x,y){if(++G[y][x]>3)G[y][x]=0,S(x+1,y),S(x-1,y),S(x,y+1),S(x,y-1);a=x<a?x:a;b=y<b?y:b;c=x>c?x:c;d=y>d?y:d;}F(t){for(;t--;)S(49,49);for(y=b;y<=d;y++){for(x=a;x<=c;x++)printf("%d ",G[y][x]);puts("");}}

/* call it like this */
main(_,v)char**v;{F(atoi(v[1]));}

โอเคฉันยอมแพ้: ทำไมอาร์เรย์ของคุณถึง 99 คูณ 98
Eric Tressler

@EricTressler ฉันไม่พบในการทดสอบได้อย่างไร!
Jerry Jeremiah


1

PHP, 213 ไบต์

function d($x,$y){global$p,$m;$m=max($m,$x);$q=&$p[$y][$x];if(++$q>3){$q=0;d($x+1,$y);d($x-1,$y);d($x,$y+1);d($x,$y-1);}}while($argv[1]--)d(0,0);for($y=-$m-1;$y++<$m;print"\n")for($x=-$m;$x<=$m;)echo+$p[$y][$x++];

สร้างกองซ้ำในการ$pจำขนาดใน$m; จากนั้นพิมพ์ด้วยลูปซ้อนกัน ทำงานด้วย
-r

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.