정체성 샌드 파일 찾기


18

이 질문은 아벨 리안 사포 에 관한 것이다. 읽기 이 이전의 도전을 하고 이 numberphile 비디오를 볼 자세한 내용을 보려면.


크기가 n x n 인 아벨 리안 샌드 파일은 숫자 0, 1, 2 및 3 (모래 입자 수를 나타냄)을 포함하는 그리드입니다. 이 sandpiles를 추가하면 첫 번째 요소에 의해 요소를 추가 한 다음에 의해 작동 전복 3. 중요하지, 최종 결과는 동일 않습니다 전복되는 순서 초과 할 때 어떤 요소를. 셀이 넘어지면 그 수가 4만큼 감소하고 직접 이웃 각각이 1 씩 증가합니다. 이것은 연쇄 반응을 일으킬 수 있습니다. 셀이 격자의 가장자리에있는 경우 이동 중에 격자에서 떨어진 결이 사라집니다.

예를 들어, 두 개의 3 x 3 샌드 필을 추가하고 있습니다 (약간의 연쇄 반응을 나타냄).

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

이 도전에서 우리는 가능한 모든 n x n 샌드 필 의 부분 집합에 관심이 있습니다. 이 부분 집합에는 모든 3s n by n sandpile에 임의의 sandpile을 추가하여 얻을 수있는 모든 sandpile이 포함됩니다. 예를 들어, 바로 위 212 | 101 | 212의 그림이 모두 3 개의 샌드 파일에 무언가를 추가했기 때문에 부분 집합에 있음을 알았 습니다.

이제이 부분 집합에는 흥미로운 요소 인 identity 요소가 있습니다. 이 요소를 가져 와서 하위 집합의 다른 요소에 추가 하면 합계는 변경되지 않습니다. 다시 말해,이 샌드 파일 은이 부분 집합 의 0 과 같은 역할 을합니다. 너무 그렇게 212 | 101 | 212예를 들어 3 3의 부분 집합에 대한 제로 요소입니다 :

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

이제 이것은 당신의 도전입니다 : 주어진 n , n by n grid 의 부분 집합의 identity 요소를 찾으십시오 . 선택한 대비가 충분한 고유 한 색상을 각 색상에 할당하고 0, 1, 2, 3n x n 이미지를 출력하여 출력하십시오. 귀하의 코드는 합리적인 최신 PC에서 1 분 안에 50 x 50 개의 케이스를 생성 할 수 있어야합니다.


예를 들어 500 x 500 ID 요소는 다음과 같습니다.

500 x 500 요소

여기에 blue = 3, green = 2, red = 1, white = 0입니다. 그러나이 색 구성표를 답에 사용할 필요는 없습니다.


2
경쟁 업체에 경고의 말 : 솔루션을 계산하는 방법이 아니라 솔루션이 무엇인지 설명했습니다. 코드는 1 분 안에 50 x 50 개의 사례를 생성 할 수 있어야하므로 무차별 강제 적용은 불가능합니다. 이 문제를 해결하는 알고리즘이 있으며 제공하지는 않습니다. 의도적입니다. 나는 너무 많은 도전이 당신에게 미리 씹힌 음식을 제공한다고 생각합니다. 나는 내 재량에 따라 내장 (당신을보고, Mathematica)의 문제를 사소하게하지 않는 첫 번째 답변에 + 100 현상금을 줄 것입니다.
orlp

2
500x500 이미지의 이미지는 각 색상이 어떤 숫자에 해당하는지 말하는 것이 좋습니다.
xnor

"충분한 대비"는 무엇입니까?
코너 오브라이언

@ ConorO'Brien 충분히 구별 할 수있는 모든 색상 세트. 나는 약간의 색상 측정으로 100 % 객관적으로 만들 수 있지만 과잉이라고 생각합니다. 빨간색, 노란색, 녹색, 회색조 등을 사용하더라도 상관 없습니다. 서로의 1 % 이내 (예 : # 000000, # 000001, # 000002, # 000003)의 4 가지 회색 음영을 사용하지 마십시오.
orlp

ahem 이 질문은 이제 현상금을받을 자격이 있다고 생각합니다. +100 보너스를받을 수 있습니까? :)
JungHwan Min

답변:


2

옥타브, 120 113 바이트

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)))

Mathematica 답변의 참고 논문에 대한 링크를 제공 한 JungHwan Min 에게 감사합니다 . Stewie Griffin
덕분에 7 바이트가 절약되었습니다.[any(any(x)) -> nnz(x)]

여기에는 두 가지 기능이 사용됩니다.

1. f: 행렬의 안정화를 위해
2. n입력으로 사용하고 단위 행렬을 보여주는 익명 함수 .

rextester에서 사용해보십시오! 50 * 50 매트릭스 생성 용

행렬 계산에 소요되는 시간 : 0.0844409 seconds.

설명:

f 행렬을 안정화시키는 함수 를 생각해보십시오. 항등을 찾는 작업은 간단합니다.

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

이는 ones(n)*66의 * n 행렬 을 의미합니다.

그래서 n=3:

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

결과는 f(M-f(M))

안정화 기능을 위해 작업 속도를 높이는 데 사용되는 2D 컨벌루션; 각 반복 b에서 입력 행렬과 동일한 크기의 이진 행렬 을 만들고 입력 행렬의 해당 요소가> 3이면 1로 설정합니다. 그런 다음 이진 행렬의 2D 컨벌루션을 다음 마스크로 적용합니다.

0 1 0
1 0 1
0 1 0

네 개의 직접 이웃을 나타냅니다.
컨벌루션 결과가 행렬에 추가되고 이진 행렬에서 4 배를 뺍니다.

루프는 행렬의 모든 요소가 <= 3이 될 때까지 계속되었습니다.

언 골프 버전 :

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

매쓰, 177 157 135 133 바이트

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]]&

숫자를 n받습니다. 결과는 신원 Sandpile입니다. 0은 검은 색, 1은 밝은 회색, 2는 자홍색, 3은 청회색입니다.

슬프게도, Mathematica에는이를위한 내장 기능이 없습니다 ...

Scott Corry 및 David Perkinson의 논문에 명시된 알고리즘을 사용합니다 .

5 살짜리 노트북에서 91.7 초가 걸리고 50x50 신분을 계산합니다. 합리적인 최신 데스크톱 컴퓨터가 50 % 이상 빠르다고 확신합니다. (또한 끝에 더 빠른 코드가 있습니다).

설명

f= ...

함수 정의 f(입력은 샌드 파일 매트릭스) : 함수 ...

BlockMap[ ... ]~FixedPoint~#&

... BlockMap출력이 변경되지 않을 때까지 작업을 반복합니다 . BlockMap작업 : ...


#~ArrayPad~1

... 입력 배열을 0의 한 레이어로 채 웁니다 ...

{3,3},1

... 오프셋 1을 사용하여 3x3 행렬로 분할하십시오 ...

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

... 그리고 각 칸막이마다 중앙 셀과 중앙 셀 값 mod 4에 쌓인 모래 알갱이의 수를 추가하십시오.

즉, 출력은 f안정화 된 입력 버전입니다.


k=Table[6,#,#]

6 kn x n 배열 로 정의하십시오 .

f[k-f@k]]

f (k-f (k))를 계산합니다.

Colorize[ ... ]

결과에 색상을 적용하십시오.

빠른 버전 (142 바이트)

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]]&

동일한 코드이지만 대신 기본 제공 목록 회전을 사용 BlockMap합니다. 랩톱에서 4.0 초 동안 n = 50을 계산합니다.


시간 제한의 정신 (무차별적인 힘이 아닌 실제 알고리즘 구현)을 따랐다는 점을 고려할 때 강력한 데스크톱 컴퓨터가 50 % 더 빠르다는 것은 매우 타당합니다. 사소한 내장 기능없이 실제 알고리즘을 구현하므로 +100 보너스를받을 수 있습니다. 아직 현상금을 시작할 수 없으므로 기다려야합니다.
orlp

파이썬에서 꽤 사소하게 구현하는 것은 (명백하게 느린 언어) n = 50에 ~ 2 초 밖에 걸리지 않습니다. 어쩌면 속도를 조금 높일 수 있습니까?
orlp

@orlp 완료했지만 원래 코드보다 깁니다. 더 빠른 버전을 주요 답변으로 만들어야합니까, 아니면 마지막에 넣을 수 있습니까?
JungHwan Min

이것처럼 괜찮습니다.
orlp

0

파이썬 + 3 + NumPy와 PIL, 385 370 364 바이트

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')

STDIN에서 입력을받습니다. 이미지를에 회색조로 출력합니다 i.png. 검은 색은 0, 어두운 회색은 1, 밝은 회색은 2, 흰색은 0에 해당합니다.

공식 사용 I = R(S - R(S)), I, 정체성의 요소를S 은 6으로 채워진 행렬 R이며 감소 함수입니다.

파이썬 2로 전환하고 수행하여 바이트를 절약 할 수 있습니다. from numpy import* 하고을 있지만 (1) Python 2에 Numpy가 설치되어 있지 않고 (2) 프로그램이 종료되지 않았습니다 from numpy import*.

언 골프 드 :

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')

PIL을 사용하여 이미지를 명시 적으로 생성하지 않고 데이터를 사용 scipy하거나 matplotlib표시 하여 바이트를 절약 할 수 있습니다 .
orlp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.