Tìm bản sắc cát


18

Câu hỏi này là về những đống cát abelian . Đọc thử thách trước đóxem video số này để tìm hiểu thêm.


Một hố cát abelian có kích thước n by n là một lưới chứa số 0, 1, 2 và 3 (đại diện cho số hạt cát). Thêm hai sandpiles hoạt động bằng cách trước tiên thêm phần tử theo phần tử, sau đó lật đổ bất kỳ phần tử nào ở trên 3. Thứ tự mà bạn lật đổ không quan trọng, kết quả cuối cùng là như nhau. Khi một tế bào lật đổ số lượng của nó giảm 4 và mỗi hàng xóm trực tiếp của nó tăng thêm 1. Điều này có thể gây ra phản ứng dây chuyền. Nếu một ô nằm trên rìa của lưới, bất kỳ hạt nào rơi ra khỏi lưới trong khi lật đổ sẽ biến mất.

Ví dụ: tôi đang thêm hai 3 đến 3 sandpiles (tạo ra phản ứng dây chuyền khá cực đoan):

3 3 3   1 2 1   4 5 4    4 6 4    6 2 6    6 3 6    2 5 2    4 1 4    4 2 4    0 4 0    2 0 2    2 1 2
3 3 3 + 2 1 2 = 5 4 5 -> 6 0 6 -> 2 4 2 -> 3 0 3 -> 5 0 5 -> 1 4 1 -> 2 0 2 -> 4 0 4 -> 0 4 0 -> 1 0 1
3 3 3   1 2 1   4 5 4    4 6 4    6 2 6    6 3 6    2 5 2    4 1 4    4 2 4    0 4 0    2 0 2    2 1 2

Trong thử thách này, chúng tôi quan tâm đến một tập hợp con của tất cả n có thể bằng n sandpiles. Tập hợp con này chứa bất kỳ sandpile nào mà bạn có thể nhận được bằng cách thêm một sandpile tùy ý vào all-3s n by n sandpile. Ví dụ, ngay phía trên chúng ta đã thấy nó 212 | 101 | 212nằm trong tập hợp con, bởi vì chúng ta đã có được nó bằng cách thêm một cái gì đó vào tất cả 3 hố cát.

Bây giờ tập hợp con này có một yếu tố thú vị: yếu tố nhận dạng . Nếu bạn lấy phần tử này và thêm nó vào bất kỳ phần tử nào khác trong tập hợp con , tổng không thay đổi. Nói cách khác, đống cát này hoạt động giống như một số không của tập hợp con này. Nó chỉ xảy ra như vậy 212 | 101 | 212là phần tử 0 cho tập hợp con của 3 bằng 3. Ví dụ:

2 2 2   2 1 2   4 3 4    0 5 0    2 1 2    2 2 2
2 2 2 + 1 0 1 = 3 2 3 -> 5 2 5 -> 1 6 1 -> 2 2 2
2 2 2   2 1 2   4 3 4    0 5 0    2 1 2    2 2 2

Bây giờ đây là thử thách của bạn: cho n , tìm phần tử nhận dạng của tập hợp con của n theo lưới n . Xuất ra nó bằng cách chỉ định một màu duy nhất có đủ độ tương phản của sự lựa chọn của bạn với từng 0, 1, 2, 3và xuất ra một hình ảnh n theo n. Mã của bạn phải có thể tạo ra trường hợp 50 đến 50 trong một phút trên một PC hiện đại hợp lý.


Ví dụ: phần tử nhận dạng 500 x 500:

Yếu tố nhận dạng 500 x 500

Đây là blue = 3, green = 2, red = 1, white = 0. Nhưng bạn không phải sử dụng bảng màu này trong câu trả lời của mình.


2
Một lời cảnh báo cho các đối thủ cạnh tranh: Tôi đã mô tả giải pháp là gì, không phải cách tính toán. Mã của bạn phải có khả năng tạo ra trường hợp 50 x 50 trong vòng một phút, do đó, việc cưỡng bức không phải là một khả năng. Có các thuật toán để giải quyết điều này, và tôi không đưa cho bạn chúng. Đó là cố ý. Tôi cảm thấy có quá nhiều thử thách đưa ra cho bạn với thức ăn được nhai trước. Tôi sẽ đưa ra một khoản tiền thưởng +100 cho câu trả lời đầu tiên không tầm thường hóa vấn đề với một nội dung (nhìn vào bạn, Mathicala), theo quyết định của tôi.
orlp

2
Tôi nghĩ rằng hình ảnh của danh tính 500x500 sẽ có lợi khi nói số lượng mỗi màu tương ứng.
xnor

Những gì cấu thành "đủ tương phản"?
Conor O'Brien

@ ConorO'Brien Bất kỳ bộ màu nào đủ phân biệt. Tôi có thể làm cho nó trở thành mục tiêu 100% với một số biện pháp màu sắc, nhưng tôi cảm thấy điều đó quá mức cần thiết. Tôi không quan tâm nếu bạn sử dụng màu đỏ, vàng, xanh lục, thang độ xám hoặc bất cứ thứ gì, chỉ không sử dụng 4 màu xám trong phạm vi 1% của mỗi loại (như # 000000, # 000001, # 000002, # 000003).
orlp

ahem tôi tin rằng câu hỏi này hiện đủ điều kiện nhận tiền thưởng. Tôi có thể nhận được tiền thưởng +100 không? :)
JungHwan Min

Câu trả lời:


2

Octave, 120 113 byte

function a=W(a);while nnz(b=a>3);a+=conv2(b,[t=[0 1 0];!t;t],'same')-b*4;end;end;@(n)imagesc(W((x=ones(n)*6)-W(x)))

Cảm ơn JungHwan Min đã cung cấp một liên kết đến tài liệu tham khảo trong câu trả lời Mathicala của anh ấy.
Nhờ Stewie Griffin đã tiết kiệm cho tôi 7 byte[any(any(x)) -> nnz(x)]

Ở đây có hai chức năng được sử dụng:

1 . f: để ổn định ma trận
2. Một hàm ẩn danh lấy nđầu vào và hiển thị ma trận danh tính.

Hãy thử nó trên rextester! để tạo ma trận 50 * 50

Thời gian trôi qua để tính toán của ma trận : 0.0844409 seconds.

Giải trình:

Hãy xem xét một chức năng f ổn định ma trận, nhiệm vụ tìm kiếm danh tính chỉ đơn giản là

f(ones(n)*6 - f(ones(n)*6).

điều đó ones(n)*6có nghĩa là ma trận * n là 6.

vì vậy n=3:

M = [6 6 6
     6 6 6
     6 6 6];

Kết quả sẽ là f(M-f(M))

Đối với chức năng ổn định tích chập 2D được sử dụng để tăng tốc nhiệm vụ; Trong mỗi lần lặp, chúng ta tạo một ma trận nhị phân bcó cùng kích thước của ma trận đầu vào và đặt nó thành 1 nếu phần tử tương ứng của ma trận đầu vào là> 3. Sau đó, chúng tôi áp dụng tích chập 2D của ma trận nhị phân với mặt nạ sau

0 1 0
1 0 1
0 1 0

đại diện cho bốn người hàng xóm trực tiếp.
Kết quả tích chập được thêm vào ma trận và 4 lần ma trận nhị phân được trừ từ nó.

Vòng lặp tiếp tục cho đến khi tất cả các phần tử của ma trận là <= 3

Phiên bản bị đánh cắp :

function a=stabilize(a)
    mask = [t=[0 1 0];!t;t];
    while any(any(b=a>3))
        a+=conv2(b,mask,'same')-b*4;
    end
end
n= 50;
M = ones(n)*6;
result = stabilize(M-stabilize(M));
imagesc(result);

8

Toán học, 177 157 135 133 byte

Colorize[f=BlockMap[⌊{l={0,1,0},1-l,l}#/4⌋~Total~2+#[[2,2]]~Mod~4&,#~ArrayPad~1,{3,3},1]&~FixedPoint~#&;k=Table[6,#,#];f[k-f@k]]&

Có một số n. Đầu ra là đống cát nhận dạng. 0 là màu đen, 1 là màu xám nhạt, 2 là màu đỏ tươi và 3 là màu xanh xám.

Đáng buồn thay, Mathematica không có nội dung cho ...

Sử dụng thuật toán được nêu trong bài báo của Scott Corry và David Perkinson .

Mất 91,7 giây trên máy tính xách tay 5 tuổi của tôi để tính toán hố cát nhận dạng 50x50. Tôi tự tin rằng một máy tính để bàn hiện đại hợp lý nhanh hơn 50%. (Tôi cũng có một cách mã nhanh hơn vào cuối).

Giải trình

f= ...

Hàm xác định f(đầu vào là ma trận sandpile): hàm ...

BlockMap[ ... ]~FixedPoint~#&

... Lặp lại BlockMapthao tác cho đến khi đầu ra không thay đổi. BlockMaphoạt động: ...


#~ArrayPad~1

... đệm mảng đầu vào với một lớp 0 ...

{3,3},1

... phân vùng nó thành ma trận 3x3, với độ lệch 1 ...

⌊{l={0,1,0},1-l,l}#/4⌋~Total~2+#[[2,2]]~Mod~4&

... Và đối với mỗi phân vùng, thêm số hạt cát được đổ lên ô trung tâm và giá trị ô trung tâm mod 4.

tức là đầu ra của flà phiên bản ổn định của đầu vào.


k=Table[6,#,#]

Xác định klà một n bởi n mảng 6s.

f[k-f@k]]

Tính f (k - f (k)).

Colorize[ ... ]

Áp dụng màu sắc cho kết quả.

Phiên bản nhanh hơn (142 byte)

Colorize[r=RotateLeft;a=ArrayPad;f=a[b=#~a~1;b+r[g=⌊b/4⌋,s={0,1}]+g~r~-s+r[g,1-s]+r[g,s-1]-4g,-1]&~FixedPoint~#&;k=Table[6,#,#];f[k-f@k]]&

Cùng một mã, nhưng sử dụng xoay vòng danh sách tích hợp thay vì BlockMap. Tính n = 50 trong 4.0 giây trên máy tính xách tay của tôi.


Xem xét rằng bạn tuân theo tinh thần giới hạn thời gian (thực hiện một thuật toán thực tế chứ không phải vũ phu), và rất có lý khi một máy tính để bàn mạnh mẽ nhanh hơn 50%, tôi sẽ cho phép nó. Vì nó thực hiện một thuật toán thực tế mà không tích hợp sẵn tầm thường, nên điều này đủ điều kiện nhận phần thưởng +100. Bạn sẽ phải chờ nó mặc dù, vì tôi chưa thể bắt đầu một tiền thưởng.
orlp

Điều đó đang được nói, thực hiện điều này khá tầm thường trong Python (một ngôn ngữ chậm nổi tiếng), chỉ mất ~ 2 giây cho n = 50. Có lẽ bạn có thể tăng tốc nó lên một chút?
orlp

@orlp Xong, nhưng nó dài hơn mã gốc. Tôi có nên biến phiên bản nhanh hơn thành câu trả lời chính của mình hay tôi chỉ có thể đặt nó ở cuối?
JungHwan Min

Như thế này là tốt, tôi nghĩ.
orlp

0

Python 3 + Numpy + PIL, 385 370 364 byte

import numpy as q,PIL.Image as w
n=int(input())
z=n,n
def r(p):
 while len(p[p>3]):
  for x,y in q.ndindex(z):
   if p[x,y]>3:
    p[x,y]-=4;p[x-1,y]+=x>0;p[x,y-1]+=y>0
    if~-n>x:p[x+1,y]+=1
    if~-n>y:p[x,y+1]+=1
s=q.full(z,6)
t=s.copy()
r(t)
i=s-t
r(i)
w.fromarray(q.uint8(q.array(q.vectorize(lambda x:[x//1*65]*3,otypes=[object])(i).tolist()))).save('i.png')

Đưa đầu vào vào STDIN. Xuất ra hình ảnh như thang độ xám i.png. Màu đen tương ứng với 0, màu xám đậm đến 1, màu xám nhạt đến 2 và màu trắng là 0.

Sử dụng công thức I = R(S - R(S)), trong đó Ilà phần tử nhận dạng, Slà ma trận chứa đầy sáu phần và Rlà hàm khử.

Tôi có thể có thể lưu một số byte bằng cách chuyển sang Python 2 và thực hiện from numpy import*, nhưng (1) Tôi không cài đặt Numpy trên Python 2 và (2) chương trình không kết thúc from numpy import*.

Ung dung:

import numpy as np
from PIL import Image

# Compute the identity element

n = int(input('Size of the sandpile: '))

def reduce_pile(sandpile):
  while any(element >= 4 for element in np.nditer(sandpile)):
    for x, y in np.ndindex((n, n)):
      if sandpile[x, y] >= 4:
        sandpile[x, y] -= 4
        if x > 0: sandpile[x - 1, y] += 1
        if y > 0: sandpile[x, y - 1] += 1
        if x < n - 1: sandpile[x + 1, y] += 1
        if y < n - 1: sandpile[x, y + 1] += 1

s = np.full((n, n), 6, dtype=np.int32)
s_prime = np.copy(s)

reduce_pile(s_prime)

identity = s - s_prime
reduce_pile(identity)

# Output it to identity.png as an image

colours = [[255, 255, 255], [255, 0, 0], [0, 255, 0], [0, 0, 255]]
img_array = np.vectorize(lambda x: colours[x], otypes=[object])(identity)
img_array = np.array(img_array.tolist(), dtype=np.uint8)

img = Image.fromarray(img_array)
img.save('identity.png')

Bạn có thể lưu byte bằng cách sử dụng scipyhoặc matplotlibhiển thị dữ liệu thay vì tạo hình ảnh rõ ràng bằng PIL.
orlp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.