폭발 숫자


25

샌드 박스 (삭제됨)

9S 등의 매트릭스 정의 할 수 :

N=[999999999]

폭발하는 숫자를 위치 (x,y) 에서 인접한 모든 이웃 (자체 포함) 사이에서 동일한 정수로 분해 할 수 있고 각 부분의 절대 값이 0보다 큰 숫자로 정의 할 수 있습니다.

이전의 행렬에서의 위치에 번호를 분해 수 (1,1) (인덱스 0)

N=[999999999]
N=[9+19+19+19+10+19+19+19+19+1]

N=[10101010110101010]

때로는 결과를 1보다 큰 합리적인 숫자로 분해하는 경우가 있습니다. 이는 숫자를 폭발시킬 때 피해야하는 것입니다. 이 경우 나머지는 분해 된 번호에 할당됩니다.

이를 입증하기 위해 이전 매트릭스를 계속 사용하십시오. 이번에는 위치 ( 0 , 0 ) 에서 숫자를 분해합니다.(0,0)

N=[10101010110101010]

여기에는 3 개의 neightbor와 숫자 자체가 있습니다. 여기 방정식은 같은 것입니다 10/4 우리에게주는 2 각과 (2)를 나머지로는.

N=[2+210+21010+21+210101010]

N=[4121012310101010]

또한, 때때로 그의 이웃들 사이의 동일한 부분들 (abs가 0보다 큰 곳)에서 분해되기에 충분히 크지 않을 것이다 (이론 수 | <1). 이 경우 "0보다 큰" 조건 을 유지하려면 분해 된 숫자에서 "빌려 "야 합니다. 이전 예제를 계속 진행하고 위치 (1,1) 에서 숫자를 분해합니다 .

N=[4121012310101010]

N=[4+112+110+112+10+1610+110+110+110+1]
N=[5131113511111111]


(x,y)


테스트 사례

입력: 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
사각형이 아닌 수학에 대한 테스트 사례를 추가하는 것이 좋습니다.
Οurous

@Ourous 어, 나는 그들이 생각하는 드로잉 보드로 다시 사각형으로 보장된다고 가정하고 내 프로그램을 작성하고 있었다
rtpax

행렬 크기가 2x2 이상이라고 가정 할 수 있습니까? 아니면 1x1 행렬도 입력 할 수 있습니까?
Kevin Cruijssen

@rtpax 질문에 달리 명시되지 않는 한 모든 형식 예
ASCII 전용

답변:


9

C (GCC) 220 216 214 212 바이트

2 바이트 동안 @ceilingcat에 크레딧

#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

자바 스크립트 (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,y)

  1. n
  2. m(x,y)/nq
  3. 매트릭스를 다시 걸어 각 이웃을 업데이트하십시오.
  4. m(x,y)

그 대신, 우리는 필요한만큼 여러 번 반복되는 더 간단한 작업 흐름을 실행하는 재귀 함수를 사용합니다.

  1. n0
  2. 빼기n+1
  3. n
  4. 참조 셀 증분 ( 마지막 재귀 호출이 완료되면 이 종류의 모든 단계가 연속적으로 실행 됨 )

주요 이점은 매트릭스에 대해 하나의 루프 만 필요하다는 것입니다. 두 번째 이점은 몫을 전혀 계산할 필요가 없다는 것입니다.

M=(0000260000) and (x,y)=(1,1)

첫 번째 반복1 단계 이후 에는 다음이 있습니다.

M=(1111271111) and n=9

이후 2 단계첫 번째 반복 :

M=(1111171111)

9+1

26

179

후에 1 단계두 번째 반복 , 우리는이 :

M=(2222182222) and n=9

그리고 두 번째 반복2 단계 후에 :

M=(222282222)

8<9

우리는 이제 두 번 (참조 셀을 증가 4 단계두 반복을 최종 결과로 이어지는) :

M=(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)개의 백틱 으로 대체하여 몇 바이트를 저장할 수 있습니다 .
얽히고 설킨

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

녹-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가 부호없는 벡터의 정수 색인을 요구하지만 부호있는 정수를 빼기 위해 음수를 요구하기 때문에 꽤 길다. 그러나 나는 지금까지 내 알고리즘이 "가장 짧은 알고리즘"이라고 생각합니다. 실제로 가장자리, 바닥 등을 감지 할 필요가 없습니다.

세 가지 사항에 주목하십시오. 하나, 모든 셀의 합은 항상 일정합니다. 둘째, 이것은 나눗셈 / 나머지 상황이므로 Bresenham 알고리즘 스타일 사고를 적용 할 수 있습니다. 셋째, 질문은 특별한 위치의 "추가"항목을 처리하기 전에 항상 특정 위치 셀의 특정 거리 내에있는 모든 셀에 동일한 숫자를 추가합니다.

연산:

위치 P에있는 셀의 원래 값을 M에 저장하십시오.

루프 시작 :

행렬의 각 셀 I을 반복합니다. 셀 I의 위치가 위치 P의 3 사분면 (제곱 거리) 내에 있으면 셀 P에서 1을 빼고 셀 I에 1을 더합니다. 행렬을 통해 한 번의 반복으로 몇 번 수행되는지 계산합니다.

위치 P의 셀에 남은 값이 M / Count + M modulo Count보다 작거나 같으면 루프를 끊습니다. 그렇지 않으면 루프를 다시 수행하십시오.

결과 매트릭스는 분해 버전이됩니다. 카운트는 기본적으로 가장자리를 다루지 않고 이웃을 계산하는 방법입니다. 루핑은 나누기 / 추가 항목을 반복되는 하나의 덧셈 / 뺄셈으로 나누는 방법입니다. 모듈로 체크는 이웃들 사이에 균등하게 나눌 수없는 '폭발'을 처리하기 위해 P 위치에 적절한 나머지가 남게합니다. do / while 루프 구조는 P <0이 올바르게 작동하도록합니다.

Rust Playground의 언 골프 버전


1
그러한 긴 함수 이름은 필요 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 답변의 반복 포트 . @Arnauld
덕분에 -17 바이트 .

바이트를 절약하기 위해 새로운 것을 반환하는 대신 입력 행렬을 수정합니다.

온라인으로 사용해보십시오.

설명:

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]ym[y][x]y

@Arnauld 아 알았어. 나는 실제로 범위를 벗어난 것이 JS에서 문제가 아니라는 것을 기억했지만 undefined[x]실패한 이유를 이해할 수 있습니다 . 어쨌든 (x-X)**2+(y-Y)**2<3수표는 꽤 똑똑합니다. 3x3 블록 (및 경계 내)에서 행렬의 값을 확인하려는 경우 기억해야합니다. 나는 실제로 그와 같은 몇 가지 대답을 가지고 있다고 생각합니다. 지금은 try-catch를 사용하고 어떤 경우에는 최종적으로 시도합니다.
Kevin Cruijssen

1
향상된 for 루프가있는 171 바이트
Arnauld

@Arnauld 아 좋은. 이제 나는 당신이 똑같은 일을하기 때문에 당신의 답변에서 포트를 만들 때 생각하지 않았다고 믿을 수 없습니다 ..>.>;)
Kevin Cruijssen

2

공통 리스프 , 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))

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.