アイデンティティサンドパイルを見つける


18

この質問はアーベルサンドパイルに関するものです。読むこの前の挑戦をしてこのnumberphileのビデオを見て多くを学ぶために。


サイズのアーベル砂山NによってNは番号0、1、2及び3(砂の粒の数を表す)を含むグリッドです。2 sandpilesを追加すると、最初の要素で要素を追加し、その後で働く転倒 3.あなたがいない問題で、最終結果は同じであるん打倒する順番以上になる任意の要素を。セルが転倒すると、その数は4減少し、直接隣接するセルはそれぞれ1増加します。これにより、連鎖反応が発生する可能性があります。セルがグリッドの端にある場合、転倒中にグリッドから落ちる粒子はすべて消えます。

たとえば、2 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

この課題では、我々はすべての可能なサブセットに興味のnnは sandpiles。このサブセットは、すべての-3Sに任意の砂山を追加することによって得ることができることを任意の砂山含まNによりn個の砂山を。たとえば、上記の例212 | 101 | 212ではサブセットに含まれていることがわかりました。これは、すべて3つのサンドパイルに何かを追加することで得られたためです。

現在、このサブセットには興味深い要素、アイデンティティ要素があります。この要素を取得してサブセット内の他の要素に追加すると、合計は変更されません。つまり、この砂山はこのサブセットのゼロのように機能します。それ212 | 101 | 212は3 x 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によるn個のグリッドを。それぞれに十分なコントラストのある一意の色を割り当てて0, 1, 2, 3、n x nの画像を出力することで出力します。あなたのコードは、合理的な最新のPCで1分以内に50 x 50のケースを生成できなければなりません。


たとえば、500 x 500のアイデンティティ要素:

500 x 500のアイデンティティ要素

ここでは、青= 3、緑= 2、赤= 1、白= 0です。しかし、答えにこの配色を使用する必要はありません。


2
競合他社への警告:私はソリューションの計算方法ではなく、ソリューションとは何かを説明しました。コードは1分以内に50 x 50のケースを生成できる必要があるため、ブルートフォースは不可能です。これを解決するアルゴリズムがありますが、私はそれらを提供していません。それは意図的です。あまりにも多くの課題が、噛みごたえのある食べ物をもたらすと感じています。私の判断で、組み込み関数(Mathematicaを見て)の問題を軽視しない最初の回答に+100の賞金を与えます。
orlp

2
500x500のアイデンティティーの画像は、各色が何の数字に対応するかを言うことから恩恵を受けると思います。
-xnor

「十分なコントラスト」とは何ですか?
コナーオブライエン

@ ConorO'Brien十分に識別可能な色のセット。色を測ることで100%客観的にすることもできますが、それはやり過ぎだと感じています。赤、黄、緑、グレースケールなどを使用するかどうかは気にせず、お互いの1%以内にある4色のグレーを使用しないでください(#000000、#000001、#000002、#000003など)。
-orlp

ahemこの質問は現在、賞金の対象になっていると思います。+100のボーナスをもらえますか?:)
ジョンファンミン

回答:


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

ここでは、2つの関数が使用されます。

1 .:fマトリックスの安定化
2. n入力として受け取り、単位マトリックスを表示する匿名関数。

rextesterで試してみてください!50 * 50マトリックスの生成用

行列の計算の経過時間:0.0844409 seconds

説明:

f 行列を安定させる関数を考えます。アイデンティティを見つけるタスクは単純です

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

つまりones(n)*6、6の* 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人の直接の隣人を表します。
畳み込みの結果がマトリックスに加算され、バイナリマトリックスの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

Mathematicaの、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。出力はIDサンドパイルです。0は黒、1は明るい灰色、2はマゼンタ、3は青灰色です。

残念ながら、Mathematicaにはこの機能が組み込まれていません...

Scott CorryとDavid Perkinsonの論文に記載されているアルゴリズムを使用します。

5歳のラップトップで91.7秒かかり、50x50のアイデンティティサンドパイルを計算します。合理的な最新のデスクトップコンピューターが50%以上高速であると確信しています。(最後に、より高速なコードもあります)。

説明

f= ...

関数を定義しますf(入力はサンドパイル行列です):...

BlockMap[ ... ]~FixedPoint~#&

... BlockMap出力が変更されなくなるまで操作を繰り返します。BlockMap操作:...


#~ArrayPad~1

...入力配列に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,#,#]

定義kとしてNによってN個 6Sのアレイ。

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

そうは言っても、これをPython(非常に遅い言語)で非常に簡単に実装すると、n = 50で2秒しかかかりません。
orlp

@orlp完了しましたが、元のコードよりも長いです。高速バージョンを主な答えにするべきですか、それとも最後に置くことができますか?
ジョンファンミン

このように大丈夫だと思います。
orlp

0

Python 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縮小関数です。

Python 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.