Patlayan sayılar


25

sanal alan (silindi)

9'lu bir matris tanımlayalım:

N=[999999999]

Haydi, patlayan bir sayıyı (x,y) pozisyonundaki bir sayı olarak tanımlayalım , tüm komşu komşuları (kendisi de dahil olmak üzere) arasında eşit tam sayılara ayrıştırılabilir ve her bir kısmın mutlak değeri 0'dan büyüktür.

Önceki matriste göre, numarayı (1,1) (indekslenmiş) pozisyonda patlatalım

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

N=[10101010110101010]

Bazen, ayrıştırma işlemi 1'den büyük rasyonel bir sayıya yol açar. Bu, sayıları patlatırken kaçınmamız gereken bir şeydir. Bu durumda, kalanlar patlamış numaraya atanacaktır.

Bunu göstermek için önceki matrisimizle çalışmaya devam edelim. Bu kez pozisyondaki sayıyı patlatacağız (0,0)

N=[10101010110101010]

Burada 3 komşumuz ve sayımız var. Burada denklemi gibi bir şeydir 10/4 bize vermek 2 her biri için ve 2 bakiye olarak.

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

N=[4121012310101010]

Ayrıca, bazen bir sayı komşuları (| rasyonel sayı | <1) arasında eşit kısımlarda (abs'in 0'dan büyük olduğu) ayrışacak kadar büyük olmayacaktır. Bu durumlarda , "0'dan büyük" durumu korumak için patlatılmış numaradan "ödünç almamız " gerekir . Önceki örneğimize devam edelim ve sayıyı ( 1 , 1 ) pozisyonunda patlatalım .(1,1)

N=[4121012310101010]

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


Zorluk , (x,y) konumlarının bir listesi ve sonlu boş olmayan bir doğal sayı dizisi verildiğinde, konum listesindeki her sayı patlatıldıktan sonra patlatılmış formu döndürür.


Test durumları

Giriş: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]

Çıktı: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]


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

Çıktı: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]


Giriş: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]

Çıktı: [[-9, 3],[3, 3]]


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

Çıktı: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]


Giriş: Initial Matrix: [[1]], numbers: [[0,0]]

Çıktı: [[1]]


Giriş: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]

Çıktı: [[1, 1, 4]]


notlar

  • Giriş / Çıkış kuralları geçerlidir

  • Giriş matrisinin asla boş olmayacağını varsayabilirsiniz.

  • Koordinatların her zaman geçerli olacağını varsayabilirsin

  • Test durumlarında girdi koordinatı (satır, sütun) şeklinde verilmiştir. Olması gerekiyorsa (x, y) değerleri değiştirebilirsiniz. Eğer öyleyse, lütfen cevabınızı belirtiniz


golf kodunda yeni; bu matrisleri almak için numunenin hangi formata girmesine izin verilir? Dilde var olan herhangi bir format? Dize formu tam olarak yazıldığı gibi?
rtpax

1
Kare olmayan matrisler için bir test vakası eklemenizi öneririm.
Büyük

@Ourous uh oh, programımın, kare olmaları garanti edildiğini varsayıyordum, çizim tahtasına geri döndüğünü sanıyorum
rtpax

Matris boyutunun en az 2'ye 2 olduğunu varsayabilir miyiz? Veya 1'e 1 matris de girilebilir mi?
Kevin Cruijssen

@rtpax Sorunun aksi belirtilmediği sürece herhangi bir format, evet
ASCII-yalnızca

Yanıtlar:


9

C (GCC) 220 216 214 212 bayt

@ceilingcat'e 2 baytlık kredi

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

Burada çalıştır

biraz daha az golf oyunu

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

Örnek olan arama kodu

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

ve çıktı

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

11
PPCG :) 'ye Hoşgeldiniz
Shaggy


7

JavaScript (ES7),  126 125 123  121 bayt

@Shaggy sayesinde 2 bayt kaydedildi

Girişi olarak alır (matrix)(list). Matrisi değiştirerek çıktı verir.

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

Çevrimiçi deneyin!

Nasıl?

(x,y)

  1. n
  2. m(x,y)/nq
  3. Her bir komşuyu güncellemek için tekrar matris boyunca yürüyün
  4. m(x,y)

Bunun yerine, gerektiğinde defalarca tekrarlanan daha basit bir işlem akışı gerçekleştiren özyinelemeli bir işlev kullanıyoruz:

  1. n0
  2. n+1
  3. n
  4. referans hücresini artırmak (bu türdeki tüm adımlar , son özyinelemeli çağrı tamamlandığında art arda yürütülür )

Asıl yarar, matris üzerinde sadece bir döngüye ihtiyacımız olmasıdır. İkinci fayda, hiç bir bölümü hesaplamamız gerekmemesidir.

Örnek

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

Sonra adım 1 arasında ilk yineleme elimizde:

M=(1111271111) and n=9

Ve sonra 2. adımda ait ilk yineleme :

M=(1111171111)

9+1

26

179

Sonra adım 1 ve ikinci tekrarında elimizde:

M=(2222182222) and n=9

Ve sonra 2. adımda ait ikinci tekrarında :

M=(222282222)

8<9

Biz şimdi iki kez (referans hücresi artırmak adım 4 arasında Her tekrar nihai sonuca giden,):

M=(2222102222)

Yorumlananlar

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
Her iki oluşumunu (0)da 2 backtick ile değiştirerek birkaç byte tasarruf edebilirsiniz .
Shaggy

6

R , 163 162 161 159 155 146 bayt

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}

Çevrimiçi deneyin!

açıklama

(Kodun önceki bir sürümüne karşılık gelir)

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

Temiz , 181 167 bayt

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

Çevrimiçi deneyin!

Kısmen uygulanmış bir fonksiyon biçiminde değişmez.

Genişletilmiş (ilk sürüm):

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

Pas - 295 bayt

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

Bu, vektörlerin işaretsiz tamsayı indekslemesini gerektiren, ancak negatif sonuçlara yol açan çıkarma yapmak için işaretli tamsayıları gerektiren Rust nedeniyle oldukça uzundur. Ancak algoritmamın şu ana kadar "en kısa algoritma" olduğuna inanıyorum. Aslında, kenarları, tabanı vb. Tespit etmeye gerek yoktur.

Üç şeye dikkat edin: Birincisi, tüm hücrelerin toplamı her zaman sabittir. İkincisi, bu bir bölünme / kalan durumdur, bu yüzden Bresenham algoritması tarzı düşüncesini uygulayabiliriz. Üç, soru, özel pozisyondaki "ekstra" eşyalarla ilgilenmeden önce, her zaman özel pozisyon hücresinin belirli bir mesafesindeki tüm hücrelere aynı sayıyı ekler.

Algoritma:

P hücresindeki orijinal değeri M konumunda saklayın.

Döngü başlayın:

Matristeki her bir hücrenin üzerinden tekrarlanır. I hücresinin konumu, P konumunun 3 Quadrance (kare mesafesi) dahilindeyse, o zaman P hücresinden 1 çıkarın ve I hücresine 1 ekleyin. Bunun matris boyunca bir yinelemede kaç kez yapıldığını sayın.

P pozisyonundaki hücrede kalan değer M / Count + M modulo Count değerinden küçük veya ona eşitse, o zaman döngüyü kırın. Aksi takdirde tekrar döngüyü gerçekleştirin.

Ortaya çıkan matris patlamış versiyon olacaktır. Say, temel olarak kenarlarla uğraşmadan komşuları saymanın bir yoludur. Döngü, bölme / ekleme malzemelerini tekrarlanan tek bir ekleme / çıkarma işlemine bölmenin bir yoludur. Modulo kontrolü, komşular arasında eşit bir şekilde bölünemeyen 'patlamalar' ile başa çıkmak için uygun P pozisyonunda kalmamızı sağlar. Do / while döngüsü yapısı P <0'ın düzgün çalışmasını sağlar.

Rust Bahçesi üzerinde Ungolfed versiyonu


1
Böyle uzun bir fonksiyon ismi gerekli değildir, olduğu gibi herhangi bir 1-byter f. Fakat muhtemelen isimsiz bir işlev kullanarak daha fazla bayttan tasarruf edebilirsiniz:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Kirill L.

3

Java 10, 194 193 191 190 184 182 171 bayt

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

İteratif liman @Arnauld 'ın JavaScript cevap . @Arnauld
sayesinde -17 bayt .

Girdiyi kaydetmek için yenisini döndürmek yerine girdi matrisini değiştirir.

Çevrimiçi deneyin.

Açıklama:

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 Ah tamam. Gerçekten de sınırların dışında olduğumu hatırladım genellikle JS’de bir sorun değil ama neden undefined[x]başarısız olacağını anlayabiliyorum . Neyse, (x-X)**2+(y-Y)**2<3çekiniz oldukça akıllı. Ne zaman bir matris içindeki değerleri 3x3 blokta (ve sınırların içinde) kontrol etmek istediğimi hatırlamam gerek. Sanırım şu anda bir dene-kullan kullan kullandığım ve bir durumda dene-nihayet bir kaç cevabım var.
Kevin Cruijssen

1
Döngüler için geliştirilmiş 171 bayt .
Arnauld

@Arnauld Oh güzel. Şimdi görüyorum ki, cevabınızdan bir port oluşturduğumda, aynı şeyi yaptığınızdan beri, bunu düşünmediğime inanamıyorum ..>.>;)
Kevin Cruijssen

2

Ortak Lisp , 498 bayt

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

Çevrimiçi deneyin!

Bu işlevi kullan (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))

Daha iyi okunabilir sürüm:

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

Çıktı örneği:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.