爆炸数字


25

沙盒(已删除)

让我们将9s的矩阵定义为:

ñ=[999999999]

让我们将爆炸数字定义为位置处的数字,该数字可以分解为所有相邻邻居(包括自身)之间的相等整数,并且每个部分的绝对值都大于0。Xÿ

从上一个矩阵开始,让位置处的数字爆炸(索引为0) 1个1个

ñ=[999999999]
ñ=[9+1个9+1个9+1个9+1个0+1个9+1个9+1个9+1个9+1个]

ñ=[101010101个10101010]

有时,将结果分解为大于1的有理数。这是爆炸数字时我们需要避免的事情。在这种情况下,余数将分配给爆炸数字。

为了演示它,让我们继续使用我们以前的矩阵。这次我们将爆炸位置00

ñ=[101010101个10101010]

在这里,我们有3个倍数和数字本身。在这里,等式类似于10/4,每个给我们2 ,余数给我们2个

ñ=[2+210+21010+21个+210101010]

ñ=[4121012310101010]

同样,有时一个数字的大小也不足以使其在邻居之间相等的部分(abs大于0)分解(|有理数| <1)。在这种情况下,我们需要从爆炸数中“借”来维持“大于0”的条件。让我们继续前面的示例,并展开位置1个1个

ñ=[4121012310101010]

ñ=[4+1个12+1个10+1个12+1个0+1个-610+1个10+1个10+1个10+1个]
ñ=[5131113-511111111]


面临的挑战是,给定一个位置列表和一个自然数的有限非空数组,在分解位置列表中的每个数字之后,返回分解形式。Xÿ


测试用例

输入: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]

输出: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]


输入: Initial matrix: [[9, 8, 7], [8, 9, 7], [8, 7, 9]], numbers: [[0,0],[1,1],[2,2]]

输出: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]


输入: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]

输出: [[-9, 3],[3, 3]]


输入: Initial Matrix: [[10, 20, 30],[30, 20, 10],[40, 50, 60]], numbers: [[0,2],[2,0],[1,1],[1,0]]

输出: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]


输入: Initial Matrix: [[1]], numbers: [[0,0]]

输出: [[1]]


输入: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]

输出: [[1, 1, 4]]


笔记

  • 输入/输出规则适用

  • 您可以假设输入矩阵永远不会为空

  • 您可以假设坐标总是有效的

  • 测试用例中的输入坐标为(行,列)。如果需要将其设为(x,y),则可以交换值。如果是这样,请在回答中说明


高尔夫新手;样本可以采用哪种格式摄取这些矩阵?语言是否存在任何格式?字符串形式完全如写?
rtpax

1
我建议为非平方矩阵添加一个测试用例。
很有可能

@Ourous嗯,哦,我一直在编写自己的程序,假设它们可以保证是正方形的,回到我猜是绘图板
rtpax

我们是否可以假设矩阵大小至少为2 x 2?还是也可以输入一个1矩阵?
凯文·克鲁伊森

@rtpax除非问题另有说明,否则为任何格式,是
仅ASCII格式的

Answers:


9

C(GCC)220 216 214 212字节

贷记给@ceilingcat 2字节

#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R,int C,int*m){for(int*i=m+R*C;~*i;) {int*M,l=*i+++C**i++,a=0,b;L(r)L(c)P?:++a;M=m+l;b=*M/a;b+=!b;*M- =b*a;L(r)L(c)M[r*C+c]+=P?0:b;}}

在这里运行

略少打高尔夫球的版本

#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R, int C, int*m) {
    for(int*i=m+R*C;~*i;) {
        int*M,l=*i+++C**i++,a=0,b;
        L(r)
            L(c)
                P?:++a;
        M=m+l;
        b=*M/a;
        b+=!b;
        *M-=b*a;
        L(r)
            L(c)
                M[r*C+c]+=P?0:b;
    }
}

带有示例的调用代码

int main()
{
  int matrix[] = {3,3,3,3,3,3,3,3,3,0,0,0,1,0,2,-1};
  int rows = 3;
  int columns = 3;
  f(rows,columns,matrix);
  for(int r = 0; r < rows; ++r) {
    for(int c = 0; c < columns; ++c) {
      printf("%03d,",matrix[r*columns + c]);
    }
    printf("\n");
  }
}

和输出

001,005,003,
000,006,003,
001,005,003,

11
欢迎来到PPCG :)
Shaggy


7

的JavaScript(ES7), 126个125 123  121字节

@Shaggy节省了2个字节

将输入作为(matrix)(list)。通过修改矩阵的输出。

m=>a=>a.map(([Y,X])=>(g=n=>m[m.map((r,y)=>r.map((_,x)=>(x-X)**2+(y-Y)**2<3&&r[n++,x]++)),(m[Y][X]+=~n)<n||g``,Y][X]++)``)

在线尝试!

怎么样?

Xÿ

  1. ñ
  2. Xÿ/ñq
  3. 再次遍历矩阵以更新每个邻居
  4. Xÿ

取而代之的是,我们使用递归函数来执行更简单的操作流程,并根据需要重复多次:

  1. ñ0
  2. ñ+1个
  3. ñ
  4. 递增参考单元格(当最后一个递归调用完成时,将依次执行所有此类步骤)

主要好处是我们只需要在矩阵上进行一个循环即可。第二个好处是我们根本不需要计算任何商。

中号=0000260000 和 Xÿ=1个1个

第1步中的第一次迭代,我们有:

中号=1个1个1个1个271个1个1个1个 和 ñ=9

第一次迭代的步骤2之后:

中号=1个1个1个1个171个1个1个1个

-9+1个

26

179

第1步中的第二次迭代,我们有:

中号=222218岁2222 和 ñ=9

第二次迭代的步骤2之后:

中号=222282222

8<9

我们现在增加引用单元格两次(第4步两个迭代),导致最终的结果:

中号=2222102222

已评论

m => a =>                     // m[] = input matrix, a[] = list of positions
  a.map(([Y, X]) => (         // for each pair (X, Y) in a[]:
    g = n =>                  //   g = recursive function expecting n = 0
      m[                      //
        m.map((r, y) =>       //     for each row r[] at position y in m[]:
          r.map((_, x) =>     //       for each value at position x in r[]:
            (x - X) ** 2 +    //         if the quadrance between (x, y)
            (y - Y) ** 2 < 3  //         and (X, Y) is less than 3:
            && r[n++, x]++    //           increment n and increment r[x]
          )                   //       end
        ),                    //     end
        (m[Y][X] += ~n)       //     subtract n + 1 from m[Y][X]
        < n                   //     if the result is greater than or equal to n:
        || g``,               //       do a recursive call
        Y                     //     
      ][X]++                  //     increment m[Y][X]
    )``                       //   initial call to g
  )                           // end

1
您可以通过用(0)2个反引号替换两次出现来节省几个字节。
毛茸茸的

6

[R 163个 162 161 159 155 146字节

function(m,l){for(e in l){v=m[i<-e[1],j<-e[2]];s=m[x<--1:(i<dim(m))+i,y<--1:(j<ncol(m))+j];z=sum(1|s);d=max(1,v%/%z);m[x,y]=s+d;m[i,j]=v+d-d*z};m}

在线尝试!

说明

(对应于该代码的先前版本)

function(m,l) {          # Take input as matrix m and 1-indexed list of explosion points l
  for(e in l) {          # Loop over the list of explosion points
    i=e[1]; j=e[2]       # Assign current coordinates to (i,j) for brevity
    x=-1:1+i             # Assign the ranges of neighboring cells: (i-1) to (i+1),
    y=-1:1+j             # and (j-1) to (j+1)
    s=                   # Take the submatrix s=m[x,y]
      m[x<-x[x<=dim(m)]  # But first trim x and y from above to prevent out of bounds errors,
     ,y<-y[y<=ncol(m)]]  # trimming from below isn't necessary, as R tolerates index 0
    z=sum(1|s)           # Count the neighbors
    d=max(1,m[i,j]%/%z)  # Estimate, how much we'll distribute to each neighbor
    m[x,y]=s+d           # Add the distributed amount to each cell of the submatrix
    m[i,j]=m[i,j]-d*z    # Subtract the total amount from the exploded cell
  }
  m                      # Return the modified matrix
}

4

干净181个 167字节

import StdEnv;

foldl\m(x,y)={{if(d>2)0b+e-if(d>0)0b*n\\e<-:l&v<-[0..],let{b=max m.[y,x]n/n;$a b=2+sign a-(a+1)/size b;n= $x l* $y m;d=(v-x)^2+(u-y)^2}}\\l<-:m&u<-[0..]}

在线尝试!

以部分应用的函数文字形式。

扩展(第一个版本):

f // functinon f on {{Int}} and [(Int,Int)]
    = foldl \m (x, y) // fold :: (a -> b -> a) a [b] -> a with first argument \ {{Int}} (Int,Int) -> {{Int}} giving \ {{Int}} [(Int,Int)] -> {{Int}}
        = {                     // an array of
            {                   // arrays of
                if(d > 2) 0 b   // the amount we give to the neighbors
                + e             // plus the current entry
                - if(d > 0) 0 b // minus the amount taken from the target entry
                * n             // times the number of neighbors, if we're on the target
            \\                  // for each
                e <-: l         // element of row l
                & v <- [0..]    // and x-index v
                , let           // local definitions:
                    b           // the amount given to the neighbors
                        = max   // we need at least 1 each, so take the largest of
                            m.[y, x] // the target entry
                            n   // or the number of neighbors
                        / n     // divide it by the number of neighbors
                    n           // the number of neighbors
                        = (     // sum of
                            1   // one
                            + s x // if x is at the left edge = 0 else 1
                            + s ( // if x is at the right edge = 0 else 1
                                size l
                                - x 
                                - 1
                            )
                        ) * (   // times the sum of
                            1   // one
                            + s y // if y is at the top edge = 0 else 1
                            + s ( // if y is at the bottom edge = 0 else 1
                                size m
                                - y
                                - 1
                            )
                        )
                    d           // distance from the target point
                        = (v - x)^2
                        + (u - y)^2
            }
        \\                      // for each
            l <-: m             // row l in matrix m
            & u <- [0..]        // and y-index u
        }

4

Rust-295字节

fn explode(p:(i8,i8),v:&mut Vec<Vec<i8>>){let x=v[p.0 as usize][p.1 as usize];let q=|x,y|x*x+y*y;loop{let mut t=0;for i in 0..v.len(){for j in 0..v[i].len(){if q(i as i8-p.0,j as i8-p.1)<3{v[i][j]+=1;v[p.0 as usize][p.1 as usize]-=1;t+=1;}}}if v[p.0 as usize][p.1 as usize]<=(x/t+x%t){break;}}}

由于Rust需要对向量进行无符号整数索引,但是由于需要有符号整数进行减法运算而导致负值,因此这相当长。但是我相信我的算法是迄今为止的“最短算法”。实际上,无需处理检测边缘,底部等问题。

注意三件事:第一,所有单元的总和始终是常数。第二,这是除法/余数的情况,因此我们可以应用布雷森汉姆算法风格的思维。第三,在处理特殊位置的“额外”内容之前,问题始终会向特殊位置单元的一定距离内的所有单元添加相同的数字。

算法:

将单元格P的原始值存储到M中。

开始循环:

遍历矩阵中的每个单元格I。如果单元格I的位置在位置P的3个象限(平方距离)内,则从单元格P中减去1并将1加到单元格I。计算一次遍历矩阵的次数。

如果单元格中位置P剩余的值小于或等于M / Count + M模数Count,则中断循环。否则,请再次执行循环。

生成的矩阵将是分解版本。计数本质上是一种无需处理边缘即可计数邻居的方法。循环是一种将除法/加法分解为一个重复的单加法/减法的方法。模检查确保我们在位置P处留有适当的余数,以处理在邻居之间不能被平均整除的“爆炸”。do / while循环结构允许P <0正常工作。

Rust Playground上的Ungolfed版本


1
不需要这么长的函数名,任何1-byter f都可以。但是您可以通过使用匿名函数来保存更多字节:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Kirill L.

3

爪哇10,194个 193 191 190 184 182 171字节

M->C->{for(var q:C){int n,X=q[0],Y=q[1],x,y,c=0;do{c++;x=n=0;for(var r:M){y=0;for(int $:r)r[y]+=Math.hypot(x-X,y++-Y)<2?++n/n:0;x++;}}while((M[X][Y]+=~n)>=n);M[X][Y]+=c;}}

@Arnauld的JavaScript答案的迭代端口。
-17个字节感谢@Arnauld

修改输入矩阵,而不是返回新的矩阵以节省字节。

在线尝试。

说明:

M->C->{                      // Method with two integer-matrix parameters and no return-type
  for(var q:C){              //  Loop over the coordinates:
    int n,                   //   Count integer
        X=q[0],Y=q[1],       //   The current X,Y coordinate
        x,y,                 //   Temp x,y coordinates
        c=0;                 //   Counter, starting at 0
    do{                      //   Do-while:
      c++;                   //    Increase the counter `c` by 1
      x=n=0;                 //    (Re)set both `x` and the count `n` to 0
      for(var r:M)           //    Loop over the rows `r`:
        y=0;                 //     (Re)set `y` to 0
        for(int $:r)         //     Loop over the cells of the current row:
          r[y]+=             //      Increase the value at x,y by:
            Math.hypot(      //       If the hypot (builtin for `sqrt(a*a, b*b)`) of:
              x-X,           //        the difference between `x` and `X`,
                  y++-Y)     //        and difference between `y` and `Y`
                             //        (and increase `y` by 1 afterwards with `y++`)
              <2?            //       Is smaller than 2:
                 ++n/n       //        Increase count `n` and the value at x,y both by 1
                :            //       Else:
                 0;          //        Leave the value at x,y the same by increasing by 0
       x++;}}                //     Increase `x` by 1
    while((M[X][Y]+=~n)      //    Decrease the value at X,Y by n+1
          >=n);              //    Continue the do-while if this new value is still larger
                             //    than or equal to count `n`
    M[X][Y]+=c;}}            //   Increase the value at X,Y with counter `c`

1
m[y]ÿm[y][x]ÿ

@Arnauld啊,好的。我确实记得,跨界访问通常不是JS的问题,但我可以理解为什么undefined[x]会失败。无论如何,您的(x-X)**2+(y-Y)**2<3支票非常聪明。需要记住的是,当我想检查矩阵周围3x3块(以及边界内)中的值时。我想我实际上有几个这样的答案,我现在在这里使用try-catch,在某些情况下尝试-final ..请在有时间的时候看看那些。
凯文·克鲁伊森

1
171个字节,带有增强的for循环。
Arnauld

@Arnauld哦,太好了。现在我看到了,我不敢相信我从您的答案创建端口时就没有考虑过,因为您也这样做。.
>>>

2

普通Lisp,498字节

(defmacro s(l c x)`(incf(aref m,l,c),x))
(defmacro w(a &rest f)`(if(,a(or(= l 0)(= l(d 0)))(or(= c 0)(= c(d 1)))),@f))
(defmacro d(n)`(1-(array-dimension m,n)))
(defmacro p(i l m &rest f)`(loop for,i from(1-,l)to(1+,l)when(and(>=,i 0)(<=,i,m))do,@f))
(defmacro g()`(or(p i l(d 0)(p j c(d 1)(s i j 1)))(s l c(- v))))
(defun f(m l c)(let((v(w and 4(w or 6 9))))(if (<(/(s l c 0)v)1)(g)(loop for i to(1-(/(s l c 0)v))do(g)))))
(defun c(m n)(dotimes(i(length n))(f m(nth 0(nth i n))(nth 1(nth i n))))m)

在线尝试!

将此功能用作 (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))

可读性更好的版本:

(defmacro s (l c x)
  `(incf (aref m ,l ,c) ,x))

(defmacro w (a &rest f)
  `(if (,a (or (= l 0)
           (= l (d 0)))
       (or (= c 0)
           (= c (d 1))))
       ,@f))

(defmacro d (n)
  `(1- (array-dimension m ,n)))

(defmacro p (i l m &rest f)
  `(loop for ,i from (1- ,l) to (1+ ,l)
     when (and (>= ,i 0) (<= ,i ,m))
     do ,@f))

(defmacro g ()
  `(or(p i l (d 0)
     (p j c (d 1)
        (s i j 1)))
      (s l c (- v))))

(defun f (m l c)
  (let ((v (w and 4 (w or 6 9))))
    (if (< (/ (s l c 0) v) 1)
    (g)
      (loop for i to (1- (/ (s l c 0) v))
        do (g)))))

(defun c (m n)
  (dotimes (i (length n))
    (f m (nth 0 (nth i n))
       (nth 1 (nth i n))))
  m)

输出示例:

(print (c #2A((3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3)) '((5 0)(4 1)(0 2))))
;; #2A((3 4 0) (3 4 4) (3 3 3) (4 4 4) (5 -4 4) (1 5 4))

(print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
; #2A((1 0 1) (5 6 5) (3 3 3))  => #2A((1 0 1) (5 6 5) (3 3 3))

(print (c #2A((9 8 7) (8 9 7) (8 7 9)) '((0 0)(1 1)(2 2))))
;; #2A((4 11 8) (11 5 10) (9 10 4))  => #2A((4 11 8) (11 5 10) (9 10 4))

(print (c #2A((0 0) (0 0)) '((0 0)(0 0)(0 0))))
;; #2A((-9 3) (3 3))  => #2A((-9 3) (3 3))

(print (c #2A((10 20 30)(30 20 10)(40 50 60)) '((0 2)(2 0)(1 1)(1 0))))
;; #2A((21 38 13) (9 12 21) (21 71 64))  => #2A((21 38 13) (9 12 21) (21 71 64))

2

Python 2,171字节

M,p=input()
l=len
for i,j in p:
 y=[(i+y,j+x)for x in-1,0,1for y in-1,0,1if l(M)>j+x>-1<i+y<l(M[0])];x=max(M[i][j]/l(y),1);M[i][j]-=x*l(y)
 for i,j in y:M[i][j]+=x
print M

在线尝试!

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.