Вибухові числа


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)

N=[10101010110101010]

Тут ми маємо 3 сусідів і саме число. Тут рівняння що - щось на зразок 10/4 , які дають нам 2 для кожного і 2 , як залишок.

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

N=[4121012310101010]

Крім того, іноді число не буде достатньо великим, щоб розкласти його в рівних частинах (де абс більший за 0) між його сусідами (| раціональне число | <1). У цьому випадку нам потрібно "запозичити" з вибухованого числа, щоб підтримувати стан "більше 0" . Давайте продовжимо наш попередній приклад і підірвемо число в положенні (1,1) .

N=[4121012310101010]

N=[4+112+110+112+10+1-610+110+110+110+1]
N=[5131113-511111111]


Завдання задається переліком (х,у) позицій та кінцевий не порожній масив натуральних чисел, повертає вибухнуту форму після того, як кожне число зі списку позицій було вибухнене.


Тестові справи

Вхід: 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 uh oh, я писав свою програму, припускаючи, що вони гарантовано будуть квадратними, назад до дошки малювання, я здогадуюсь
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]++)``)

Спробуйте в Інтернеті!

Як?

Якби ми суворо дотримувались алгоритму, описаного в виклику, нам довелося б виконати наступні операції для кожної пари позицій (х,у):

  1. пройдіться по матриці, щоб обчислити кількість сусідів н
  2. обчислити м(х,у)/н і вивести кількість q що потрібно додати до кожного сусіда
  3. знову пройдіть по матриці, щоб оновити кожного сусіда
  4. оновлення м(х,у)

Замість цього ми використовуємо рекурсивну функцію, яка виконує простіший потік операцій, повторений стільки разів, скільки потрібно:

  1. для кожного сусіда та для самої контрольної комірки: збільшуйте комірку та збільшуйте лічильник н (ініціалізовано до 0)
  2. відняти н+1 з контрольної комірки
  3. якщо вищевказаний результат більший або дорівнює н, робіть рекурсивний дзвінок
  4. приріст комірки посилання (всі етапи цього типу виконуються послідовно, коли завершився останній рекурсивний виклик)

Основна перевага полягає в тому, що нам потрібен лише один цикл над матрицею. Друга перевага полягає в тому, що нам взагалі не потрібно обчислювати будь-який коефіцієнт.

Приклад

М=(0000260000) і (х,у)=(1,1)

Після кроку 1 на першій ітерації , ми маємо:

М=(1111271111) і н=9

І після кроку 2 на першій ітерації :

М=(1111171111)

Ключовим моментом тут є те, що опорний осередок оновлюється, беручи лише витрати (-9) враховувати без виграшу (+1), щоб ми знали, скільки ще можемо з цього зробити.

Отже, сума комірок більше не дорівнює 26в цей момент. Але це буде виправлено в кінці процесу, де всі прибутки від еталонної комірки обліковуються одразу.

Крок 3 з першої ітерації : тому17 більше, ніж 9, ми робимо рекурсивний дзвінок.

Після кроку 1 на другий ітерації , ми маємо:

М=(2222182222) і н=9

І після кроку 2 на другий ітерації :

М=(222282222)

Крок 3 з другої ітерації : це час, ми маємо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

Іржа - 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;}}}

Це досить довго через те, що Руст вимагає безпідписаного цілого індексації векторів, але вимагає підписаних цілих чисел для віднімання, що призводить до негативів. Однак я вважаю, що мій алгоритм є "найкоротшим алгоритмом" поки що. Насправді не потрібно мати справу з виявленням країв, дна тощо.

Зауважте три речі: По-перше, сума всіх комірок завжди постійна. По-друге, це ситуація поділу / залишку, тому ми можемо застосувати мислення в стилі алгоритму Брезена. По-третє, питання завжди додає однакову кількість до всіх комірок на певній відстані від комірки спеціального положення, перш ніж розбиратися з "зайвими" матеріалами в спеціальній позиції.

Алгоритм:

Збережіть початкове значення комірки в положенні P в M.

Почати цикл:

Ітерація над кожною клітиною I в матриці. Якщо положення комірки I знаходиться в межах 3 квадрату (відстань у квадраті) від позиції P, віднімайте 1 з комірки P і додайте 1 до комірки I. Порахуйте, скільки разів це робиться за одну ітерацію через матрицю.

Якщо значення залишку в комірці в положенні P менше або дорівнює M / Count + M По модулю Count, то розірвіть цикл. В іншому випадку виконайте цикл ще раз.

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

Версія без ігор на майданчику іржі


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

3

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

Ітеративний порт відповіді JavaScript @Arnauld .
-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] з упоза межами в порядку JS (вихід невизначений ), але m[y][x]зупоза межами буде також збій.
Арнольд

@Arnauld Ага гаразд. Я дійсно пам'ятаю поза межами, як правило, не є проблемою в JS, але я можу зрозуміти, чому undefined[x]б не вдалося. У всякому разі, ваш (x-X)**2+(y-Y)**2<3чек досить розумний. Потрібно пам'ятати, що коли мені хочеться перевірити значення в матриці в блоці 3х3 (і в межах) навколо нього. Я думаю, що у мене є кілька подібних відповідей, де я зараз використовую пробний ловлі, а в одному випадку пробую-нарешті .. Подивлюся на це, коли у мене буде деякий час.
Кевін Крейссен

1
171 байт з покращеним циклом.
Арнольд

@Arnauld О, приємно. Тепер, коли я це бачу, я не можу повірити, що я не замислювався над цим, коли створив порт з вашої відповіді, оскільки ви робите те саме ..>.>;)
Кевін Круїссен

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.