サンドパイルを倒す


12

無限の砂山、および砂山のアイデンティティ要素を見つけることに関する関連する質問があります。)

負でない整数の行列が与えられた場合、同じ次元であるが倒れた行列を返します:

  1. マトリックスに4より大きい値が含まれていない場合は、それを返します。
  2. 3より大きいすべての「セル」は4ずつ削減され、直接隣接するすべてのセル(上、下、左、および右)は、存在する場合は増分されます。
  3. 後藤1。

例:

0 1 0        0 2 0
2 4 0   ->   3 0 1
0 0 3        0 1 3

1 2 3    2 3 4    2 5 1    4 1 2    0 3 3    0 3 3    0 3 3
4 5 6 -> 2 4 4 -> 4 2 3 -> 0 5 4 -> 3 2 1 -> 3 3 1 -> 3 3 2
7 8 9    5 7 7    2 6 5    4 3 2    0 5 3    1 1 4    1 2 0

(最終結果のみを返す必要があります。到達するパスは、ここに示すパスとは異なる場合があります。転倒操作を実行する順序は関係なく、すべて同じ結果になります。)

より深い説明と動機については このNumberphileのビデオまたはアーベルの砂山モデルに関するWikipediaの記事を参照してください。

ルール:

  • 入力および出力を 標準的な方法のいずれかでます
  • 抜け穴は禁止されています
  • 入力と出力は次のとおりです。
    • ネストされたリスト: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    • 簡単なリスト: [1, 2, 3, 4, 5, 6, 7, 8, 9]および形状
    • ある種のネイティブマトリックスタイプ
    • 文字列、例えば 1 2 3\n4 5 6\n7 8 9
    • またはあなたの言語で動作する他の何か。
  • 入力と出力は同じ形式でなければなりません
  • 入力には、ここに示されているものよりも大きい数値が含まれる場合がありますが、サイズは言語の制限によって制限される場合があります(該当する場合はMAXINT相当)
  • マトリックスの形状は任意です(1x1、2x2、3x3、4x4、2x7、11x3など)。
  • 形状が0xNまたはNx0の場合を処理する必要はありません。

テストケース

[[2, 5, 4], [8, 6, 4], [1, 2, 3]] -> [[3, 3, 0], [1, 2, 2], [1, 3, 2]]
[[0, 0, 2], [1, 3, 3], [0, 0, 0]] -> [[0, 0, 2], [1, 3, 3], [0, 0, 0]]
[[9, 9, 9], [9, 9, 9], [9, 9, 9]] -> [[1, 3, 1], [3, 1, 3], [1, 3, 1]]
[[4, 5], [2, 3]] -> [[2, 3], [0, 1]]
[[2, 3, 5], [2, 2, 0]] -> [[3, 0, 2], [2, 3, 1]]
[[7]] -> [[3]]

これはで、最短のコード(言語ごと)が勝ちます。


すべての中間結果を表示しても大丈夫ですか?
-feersum

@feersum最終的な結果が明確である限り、そう思います。
L3viathan

回答:


8

MATL、17バイト

tss:"t3>t1Y6Z+w4*-+

MATL Online試しくださいまたは、すべてのテストケースを確認します

説明

プログラムは、入力の合計と同じ回数だけ反復します。これは、必要な反復回数の緩やかな上限です。

反復ごとに、サンドパイル行列のエントリが 3行列を与え、検出された104近傍マスクで畳み込まれています、。3サンドパイル行列で超過するエントリはによって削減され4、畳み込みの結果が追加されます。

サンドパイルマトリックスにを超える数がない最後の反復では3、ゼロがゼロから減算されて加算されるため、影響を受けません。

t       % Implicit input (matrix). Duplicate
ss      % Sum of matrix entries
:"      % Repeat that many times
  t     %   Duplicate
  3>    %   True for matrix entries that exceed 3
  t     %   Duplicate
  1Y6   %   Push predefined literal [0, 1, 0; 1, 0, 1; 0, 1, 0]
  Z+    %   2D convolution, keeping size
  w     %   Swap
  4*    %   Multiply by 4
  -     %   Subtract
  +     %   Add
        % Implicit end. Implicit display

3
畳み込みハイファイブ。
マーティンエンダー

@MartinEnderああ、あなたもそれを使用しました:-)仲間のコンボリューターを見るのは素敵です!私はflawrはすぐに私たちに参加します確信している
ルイスMendo

2
@LuisMendo Convolutionista
Suever

4

Mathematica、65バイト

#//.s_:>s+ListConvolve[{v={0,1,0},1-v,v},x=UnitStep[s-4],2,0]-4x&

説明

#//.s_:>...&

3より大きいすべてのパイルを倒すことにより、入力を繰り返し変換します。このプロセスは、変換がマトリックスの変更に失敗したとき(つまり、大きなパイルがもう存在しないとき)に自動的に停止します。次の式では、行列はと呼ばれsます。

...x=UnitStep[s-4]...

1現在の行列にa 4以上がある場合は常にaを持つ行列を作成し、そうでない場合はゼロを作成します。これは基本的に、どの杭を倒す必要があるかを示すマスクです。マスクを呼び出しxます。

ListConvolve[{v={0,1,0},1-v,v},x=UnitStep[s-4],2,0]

最初に、倒れた隣接杭のために各杭に追加される砂の数を計算します。これは、次の行列の畳み込みで行われますx

0 1 0
1 0 1
0 1 0

基本的に、マスク内の各フォン・ノイマン近傍の現在のセルに1を追加します。

s+...-4x

前の結果を追加しs、それからマスクの4倍を減算して、倒れた杭を減らします。


3

オクターブ、65バイト

これはあまり良くないようです、私はいくつかのトリックを見逃しているに違いありません...

m=input(0);do;m+=conv2(m>3,[0 1 0;1 -4 1;0 1 0],"same")
until m<4

使用できるOctaveのバージョンは何input(0)ですか?
-Suever

@Suever>> version ans = 4.0.1
feersum

2

JavaScript(ES6)、101 95バイト

カリー化構文のマトリックスの幅とw値の配列を使用aします(w)(a)。値の配列を返します。

w=>g=a=>(b=a.map((n,i)=>n%4+(F=d=>~m|i%w&&a[i+d]>>2)(m=w)+F(-w)+F(m=-1)+F(!++i)))+0==a+0?a:g(b)

フォーマットおよびコメント

w =>                      // main function: takes w as input, returns g
  g = a =>                // recursive function g: takes a as input
    (                     //
      b = a.map((n, i) => // for each element n at position i in a:
        n % 4 + (         //   keep only n MOD 4
          F = d =>        //   define F(): function that takes d as input
            ~m |          //     if m is not equal to -1
            i % w &&      //     or i MOD w is not null:
            a[i + d] >> 2 //       return a fourth of the value of the cell at i + d
        )(m = w) +        //   test the cell below the current cell
        F(-w) +           //   test the cell above
        F(m = -1) +       //   test the cell on the left
        F(!++i)           //   test the cell on the right
      )                   // end of map(): assign the result to b
    ) + 0 == a + 0 ?      // if b is equal to a:
      a                   //   stop recursion and return a
    :                     // else:
      g(b)                //   do a recursive call with b

テストケース


1

JavaScript(ES6)、118 114 104バイト

@Neilのおかげで2バイト節約

f=a=>a.find(b=>++y&&b.find(c=>++x&&c>3,x=0),y=0)?f(a.map(b=>b.map(c=>c+=--i|y?i*i+y*y==1:-4,i=x,--y))):a

DOESの(i-=x)|y-j?i*i+ヘルプ?
ニール

@Neilそれは確かに、感謝します!
-ETHproductions

...私は電話をしていたが、私も考えていたa.find(...b.find(...c>3&&a.map(...)))&&f(a)
ニール

@Neil私はそれが機能しないと思う、なぜなら.map突然変異しないから…
-ETHproductions

マップ内を検索内に移動するよりも突然変異コストをやや少なくすることで、次のようになります。– f=a=>a.find((b,x)=>b.find((c,y)=>c>3&&a.map(b=>b.map((_,j)=>b[j]+=x|(j-=y)?x*x+j*j==1:-4)&x--)))&&f(a)
ニール

1

C ++、261 258 250バイト

#import<vector>
#define S size()
void f(std::vector<std::vector<int>>&m){s:int i,j,r;for(i=r=0;i<m.S;++i)for(j=0;j<m[i].S;++j){if(m[i][j]>3){r=1;m[i][j]-=4;j>0&&m[i][j-1]++;i>0&&m[i-1][j]++;j<m[i].S-1&&m[i][j+1]++;i<m.S-1&&m[i+1][j]++;}}if(r)goto s;}

ベクトルのベクトルへの参照として入力を受け取り、それを直接変更します。

オンラインでお試しください!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.