Взрывающиеся числа


25

песочница (удалена)

Давайте определим матрицу из 9 с:

Nзнак равно[999999999]

Давайте определим взрывающееся число как число в позиции которое можно разложить на равные целые числа между всеми соседними соседями (включая себя), и абсолютное значение каждой части больше 0.(Икс,Y)

Из предыдущей матрицы давайте разберем число в позиции (0 проиндексировано) N = \ begin { bmatrix} 9+ \ color {red} 1 & 9 + \ color {red} 1 & 9 + \ color {red} 1 \\ 9+ \ color {red} 1 & \ color {blue} 0+ \ color {red} 1 & 9 + \ color {red} 1 \\ 9+ \ color {red} 1 & 9 + \ color {red} 1 & 9 + \ color {red} 1 \ end {bmatrix}(1,1)

Nзнак равно[999999999]
Nзнак равно[9+19+19+19+10+19+19+19+19+1]

Nзнак равно[10101010110101010]

Иногда разложение приводит к рациональному числу, большему, чем 1. Это то, что нам нужно избегать при разложении чисел. В этом случае остаток будет присваиваться разнесенному номеру.

Чтобы продемонстрировать это, давайте продолжим работать с нашей предыдущей матрицей. На этот раз мы взорвем число в позиции (0,0)

Nзнак равно[10101010110101010]

Здесь у нас есть 3 соседей и сам номер. Здесь уравнение примерно 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+1-610+110+110+110+1]
Nзнак равно[5131113-511111111]


Задача состоит в том, чтобы, учитывая список позиций и конечный непустой массив натуральных чисел, вернуть разобранную форму после того, как каждое число из списка позиций было взорвано.(Икс,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

Можем ли мы предположить, что размер матрицы составляет не менее 2 на 2? Или можно также ввести матрицу 1 на 1?
Кевин Круйссен

@rtpax Любой формат, если в вопросе не указано иное, да
только ASCII

Ответы:


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 байт

Сохранено 2 байта благодаря @Shaggy

Принимает вход как (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]++)``)

Попробуйте онлайн!

Как?

(Икс,Y)

  1. N
  2. м(Икс,Y)/NQ
  3. пройтись по матрице снова, чтобы обновить каждого соседа
  4. м(Икс,Y)

Вместо этого мы используем рекурсивную функцию, которая выполняет более простой поток операций, повторяемый столько раз, сколько необходимо:

  1. N0
  2. N+1
  3. N
  4. увеличить ссылочную ячейку (все шаги такого рода выполняются последовательно после завершения последнего рекурсивного вызова)

Основным преимуществом является то, что нам нужен только один цикл по матрице. Второе преимущество заключается в том, что нам вообще не нужно вычислять частное.

пример

Mзнак равно(0000260000) а также (Икс,Y)знак равно(1,1)

После шага 1 на первой итерации , мы имеем:

Mзнак равно(1111271111) а также Nзнак равно9

И после шага 2 на первой итерации :

Mзнак равно(1111171111)

-9+1

26

179

После шага 1 на второй итерации , мы имеем:

Mзнак равно(2222182222) а также 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 требует индексирования целых чисел без знака, но требует, чтобы целые числа со знаками делали вычитание, что приводит к отрицательным значениям. Однако я считаю, что мой алгоритм является «самым коротким алгоритмом» до сих пор. На самом деле нет необходимости иметь дело с обнаружением краев, дна и т. Д.

Обратите внимание на три вещи: во-первых, сумма всех ячеек всегда постоянна. Во-вторых, это ситуация деления / остатка, поэтому мы можем применить мышление в стиле алгоритма Брезенхема. В-третьих, вопрос всегда добавляет одно и то же число ко всем ячейкам на определенном расстоянии от ячейки специальной позиции, прежде чем иметь дело с «лишними» вещами в специальной позиции.

Алгоритм:

Сохранить исходное значение ячейки в позиции P в M.

Начать цикл:

Итерация по каждой ячейке I в матрице. Если положение ячейки I находится в пределах 3 квадрантов (квадратное расстояние) от положения P, то вычтите 1 из ячейки P и добавьте 1 к ячейке I. Посчитайте, сколько раз это делается за одну итерацию матрицы.

Если значение, оставшееся в ячейке в позиции P, меньше или равно M / Count + M по модулю Count, то прервите цикл. В противном случае выполните цикл снова.

Полученная матрица будет разобранной версией. Счет - это в основном способ сосчитать соседей, не имея дело с ребрами. Циклы - это способ разбить вещи деления / сложения на повторяющееся одиночное сложение / вычитание одного. Проверка по модулю гарантирует, что у нас останется соответствующий остаток в позиции P, чтобы справиться со «взрывами», которые не делятся поровну между соседями. Структура цикла do / while позволяет P <0 работать правильно.

Безголовая версия на Rust Playground


1
Такое длинное имя функции не обязательно, какой-либо 1-байтовый код, как это fбыло бы. Но вы могли бы, вероятно, сохранить еще больше байтов, используя анонимную функцию:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Кирилл Л.

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

@ Arnauld Ах, хорошо. Я действительно запомнил, что «вне границ» обычно не является проблемой в JS, но я могу понять, почему не undefined[x]получится. В любом случае, ваш (x-X)**2+(y-Y)**2<3чек довольно умен. Необходимо помнить, что когда я хочу проверить значения в матрице в блоке 3х3 (и в определенных пределах) вокруг него. Я думаю, что на самом деле у меня есть несколько таких ответов, где я сейчас использую try-catch, а в одном случае - try-finally ... Посмотрим на них, когда у меня будет время.
Кевин Круйссен

1
171 байт с расширенными для циклов.
Арно

@ Arnauld О, хорошо. Теперь, когда я вижу это, я не могу поверить, что я не подумал об этом, когда создал порт из вашего ответа, поскольку вы делаете то же самое ..>.>;)
Кевин Круйссен

2

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.