翻倒沙堆


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视频或有关Abelian sandpile模型的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

Answers:


8

MATL,17个字节

tss:"t3>t1Y6Z+w4*-+

MATL在线上尝试一下验证所有测试用例

说明

程序将迭代与输入总和一样多的次数。这是所需迭代次数的宽松上限。

对于每次迭代,在沙堆矩阵超过条目3被检测,得到的基质10,其与4-邻掩模卷积。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啊,您也曾经用过它:-)很高兴见到同伴!我敢肯定,fracler很快就会加入我们的行列
Luis

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 ,否则为0。这实际上是一个面具,指示哪些桩需要倾倒。叫面具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

本质上,它为蒙版中的每个von-Neumann邻居在当前单元格中添加一个。

s+...-4x

我们将先前的结果加上s,然后从中减去四倍的蒙版以减少倾倒的桩。


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

2

JavaScript(ES6),101 95字节

采用currying语法获取矩阵的宽度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

(i-=x)|y-j?i*i+帮助吗?
尼尔

@Neil的确如此,谢谢!
ETHproductions's

...我正在打电话,但我也在考虑a.find(...b.find(...c>3&&a.map(...)))&&f(a)
尼尔

@Neil我认为这不会起作用,因为.map它不会变异...
ETHproductions 2017年

似乎使其变异所需的费用略低于在查找结果内移动地图的费用: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)
尼尔(Neil)

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;}

将输入作为向量向量的参考,并直接对其进行修改。

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.