Angka Meledak

25

kotak pasir (dihapus)

Mari kita mendefinisikan matriks 9s sebagai:

N=[999999999]

Mari kita mendefinisikan nomor meledak sebagai angka pada posisi yang dapat didekomposisi menjadi bilangan bulat yang sama antara semua tetangga yang berdekatan (termasuk itu sendiri) dan nilai absolut dari setiap bagian lebih besar dari 0.(x,y)

Dari matriks sebelumnya, mari kita meledak angka pada posisi (0 diindeks) (1,1)

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

N=[10101010110101010]

Terkadang, hasil penguraian menjadi bilangan rasional lebih besar dari 1. Ini adalah sesuatu yang perlu kita hindari saat meledak bilangan. Dalam hal ini sisanya akan ditugaskan ke nomor yang meledak.

Untuk mendemonstrasikannya, mari lanjutkan bekerja dengan matriks kami sebelumnya. Kali ini kita akan meledakkan angka pada posisi(0,0)

N=[10101010110101010]

Di sini kita memiliki 3 neightbors dan jumlahnya sendiri. Di sini persamaannya adalah sekitar yang memberi kita 2 untuk masing-masing dan 2 sebagai sisanya.10/4

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

N=[4121012310101010]

Juga, kadang-kadang angka tidak akan cukup besar untuk didekomposisi dalam bagian yang sama (di mana abs lebih besar dari 0) antara tetangganya (| angka rasional | <1). Dalam hal ini kita perlu "meminjam" dari nomor yang meledak untuk mempertahankan kondisi "lebih besar dari 0" . Mari kita lanjutkan dengan contoh kita sebelumnya dan meledak nomor di posisi .(1,1)

N=[4121012310101010]

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


Tantangannya adalah, mengingat daftar posisi dan susunan bilangan asli non-kosong yang terbatas, mengembalikan formulir yang meledak setelah setiap nomor dari daftar posisi diledakkan.(x,y)


Uji kasus

Memasukkan: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]

Keluaran: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]


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

Keluaran: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]


Memasukkan: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]

Keluaran: [[-9, 3],[3, 3]]


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

Keluaran: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]


Memasukkan: Initial Matrix: [[1]], numbers: [[0,0]]

Keluaran: [[1]]


Memasukkan: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]

Keluaran: [[1, 1, 4]]


Catatan

  • Aturan Input / Output berlaku

  • Anda dapat mengasumsikan input matriks tidak akan pernah kosong

  • Anda dapat menganggap koordinat selalu valid

  • Input coord dalam test case diberikan sebagai (baris, kolom). Jika Anda membutuhkannya (x, y) Anda bisa menukar nilainya. Jika demikian, sebutkan itu dalam jawaban Anda

Luis felipe De jesus Munoz
sumber
baru mengenal kode golf; format apa sampel diizinkan untuk mengambil matriks ini? Adakah format yang ada dalam bahasa tersebut? Bentuk string persis seperti yang tertulis?
rtpax
1
Saya sarankan menambahkan test case untuk matricies non-square.
Οurous
@Ourous eh oh, saya telah menulis program saya dengan asumsi mereka dijamin persegi, kembali ke papan gambar saya kira
rtpax
Bisakah kita mengasumsikan ukuran matriks setidaknya 2 oleh 2? Atau bisakah matriks 1 per 1 menjadi input juga?
Kevin Cruijssen
@rtpax Format apa pun kecuali pertanyaannya menyatakan sebaliknya, ya
ASCII-saja

Jawaban:

9

C (GCC) 220 216 214 212 byte

kredit ke @ceilingcat untuk 2 byte

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

Jalankan di sini

versi yang sedikit kurang golf

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

Kode panggilan dengan sebuah contoh

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

dan hasilnya

001,005,003,
000,006,003,
001,005,003,
rtpax
sumber
11
Selamat datang di PPCG :)
Shaggy
198 byte
ceilingcat
7

JavaScript (ES7),  126 125 123  121 byte

Disimpan 2 byte berkat @Shaggy

Mengambil input sebagai (matrix)(list). Keluaran dengan memodifikasi matriks.

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]++)``)

Cobalah online!

Bagaimana?

(x,y)

  1. n
  2. m(x,y)/nq
  3. berjalan melalui matriks lagi untuk memperbarui setiap tetangga
  4. m(x,y)

Alih-alih itu, kami menggunakan fungsi rekursif yang mengeksekusi aliran operasi yang lebih sederhana, diulang sebanyak yang diperlukan:

  1. n0
  2. n+1
  3. n
  4. increment cell referensi (semua langkah semacam ini dijalankan secara berurutan ketika panggilan rekursif terakhir selesai)

Manfaat utama adalah bahwa kita hanya perlu satu loop di atas matriks. Manfaat kedua adalah kita tidak harus menghitung hasil bagi sama sekali.

Contoh

M.=(0000260000) dan (x,y)=(1,1)

Setelah langkah 1 dari iterasi pertama , kami memiliki:

M.=(1111271111) dan n=9

Dan setelah langkah 2 dari iterasi pertama :

M.=(1111171111)

-9+1

26

179

Setelah langkah 1 dari iterasi kedua , kami memiliki:

M.=(2222182222) dan n=9

Dan setelah langkah 2 dari iterasi kedua :

M.=(222282222)

8<9

Kami sekarang menambah sel referensi dua kali ( langkah 4 dari kedua iterasi ), yang mengarah ke hasil akhir:

M.=(2222102222)

Berkomentar

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
Arnauld
sumber
1
Anda dapat menyimpan beberapa byte dengan mengganti kedua kemunculannya (0)dengan 2 backticks.
Shaggy
6

R , 163 162 161 159 155 146 byte

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}

Cobalah online!

Penjelasan

(Sesuai dengan versi kode sebelumnya)

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
}
Kirill L.
sumber
4

Bersih , 181 167 byte

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..]}

Cobalah online!

Dalam bentuk fungsi literal yang diterapkan sebagian.

Diperluas (versi pertama):

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
        }
Suram
sumber
4

Karat - 295 byte

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

Ini cukup lama karena Rust memerlukan pengindeksan bilangan bulat vektor yang tidak ditandatangani, tetapi mengharuskan bilangan bulat yang ditandatangani untuk melakukan pengurangan yang menghasilkan negatif. Namun saya percaya algoritma saya adalah "algoritma terpendek" sejauh ini. Sebenarnya tidak perlu berurusan dengan mendeteksi tepi, bawah, dll.

Perhatikan tiga hal: Satu, jumlah semua sel selalu konstan. Dua, ini adalah situasi pembagian / sisa, sehingga kita dapat menerapkan pemikiran gaya algoritma Bresenham. Tiga, pertanyaannya selalu menambahkan angka yang sama untuk semua sel dalam jarak tertentu dari sel posisi khusus, sebelum berurusan dengan hal-hal "ekstra" di posisi khusus.

Algoritma:

Simpan nilai sel asli pada posisi P ke dalam M.

Mulai Loop:

Iterasi setiap sel I dalam matriks. Jika posisi sel I berada dalam 3 Kuadrat (jarak kuadrat) dari posisi P, maka kurangi 1 dari sel P dan tambahkan 1 ke sel I. Hitung berapa kali ini dilakukan dalam satu iterasi melalui matriks.

Jika nilai sisa dalam sel pada posisi P kurang dari atau sama dengan M / Count + M modulo Count, maka pecahkan loop. Kalau tidak, lakukan loop lagi.

Matriks yang dihasilkan akan menjadi versi yang meledak. Count pada dasarnya adalah cara menghitung tetangga tanpa berurusan dengan edge. Looping adalah cara untuk memecah divisi / penambahan barang menjadi penambahan / pengurangan tunggal berulang. Pemeriksaan modulo memastikan kita akan memiliki sisa yang tepat di posisi P untuk menangani 'ledakan' yang tidak terbagi rata di antara tetangga. Struktur loop do / while memungkinkan P <0 untuk bekerja dengan baik.

Versi tidak dikoleksi di Rust Playground

jangan cerah
sumber
1
Nama fungsi yang panjang seperti itu tidak perlu, by-byter apa pun fakan melakukannya. Tetapi Anda mungkin bisa menyimpan lebih banyak byte, dengan menggunakan fungsi anonim:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Kirill L.
3

Java 10, 194 193 191 190 184 182 171 byte

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

Port berulang dari jawaban JavaScript @Arnauld .
-17 byte terima kasih kepada @Arnauld .

Memodifikasi input-matriks alih-alih mengembalikan yang baru untuk menghemat byte.

Cobalah online.

Penjelasan:

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`
Kevin Cruijssen
sumber
1
m[y]ym[y][x]y
@Arnauld Ah ok. Saya memang ingat di luar batas biasanya bukan masalah di JS, tapi saya bisa mengerti mengapa undefined[x]akan gagal. Lagi pula, (x-X)**2+(y-Y)**2<3cek Anda cukup cerdas. Perlu diingat bahwa ketika saya ingin memeriksa nilai dalam matriks dalam blok 3x3 (dan dalam batas) di sekitarnya. Saya pikir saya sebenarnya punya beberapa jawaban seperti itu, di mana saya sekarang menggunakan try-catch, dan dalam satu kasus try-akhirnya .. Akan melihat mereka ketika saya punya waktu.
Kevin Cruijssen
1
171 byte dengan peningkatan untuk loop.
Arnauld
@Arnauld Oh bagus. Sekarang saya melihatnya, saya tidak percaya saya tidak memikirkan hal itu ketika saya membuat port dari jawaban Anda, karena Anda melakukan hal yang sama ..>.>;)
Kevin Cruijssen
2

Common Lisp , 498 byte

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

Cobalah online!

Gunakan fungsi ini sebagai (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))

Versi lebih mudah dibaca:

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

Contoh keluaran:

(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))
adl
sumber
2

Python 2 , 171 byte

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

Cobalah online!

Erik the Outgolfer
sumber