Wybuchające liczby


25

piaskownica (usunięty)

Zdefiniujmy macierz 9s jako:

N.=[999999999]

Zdefiniujmy liczbę wybuchającą jako liczbę w pozycji którą można rozłożyć na równe liczby całkowite między wszystkimi sąsiadującymi z nią sąsiadami (w tym sobą), a wartość bezwzględna każdej części jest większa niż 0.(x,y)

Z poprzedniej macierzy rozbijmy liczbę na pozycji (indeksowane 0) N = \ begin { bmatrix} 9+ \ kolor {czerwony} 1 i 9 + \ kolor {czerwony} 1 i 9 + \ kolor {czerwony} 1 \\ 9+ \ kolor {czerwony} 1 i \ kolor {niebieski} 0+ \ kolor {czerwony} 1 i 9 + \ kolor {czerwony} 1 \\ 9+ \ color {red} 1 i 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]

Czasami rozkładanie wyniku na liczbę wymierną większą niż 1. Jest to coś, czego musimy unikać przy eksplodowaniu liczb. W takich przypadkach pozostała część zostanie przypisana do numeru rozstrzelonego.

Aby to zademonstrować, kontynuujmy pracę z naszą poprzednią matrycą. Tym razem wybuchniemy liczbą na pozycji (0,0)

N.=[10101010110101010]

Tutaj mamy 3 sąsiadów i samą liczbę. Tutaj równanie jest czymś w rodzaju 10/4 co daje nam 2 dla każdego i 2 jako resztę.

N.=[2)+2)10+2)1010+2)1+2)10101010]

N.=[41210123)10101010]

Również czasami liczba nie będzie wystarczająco duża, aby mogła zostać rozłożona na równe części (gdzie abs jest większa niż 0) między jego sąsiadami (| liczba wymierna | <1). W takich przypadkach musimy „pożyczyć” od numeru rozstrzelonego, aby utrzymać warunek „większy niż 0” . Kontynuujmy z naszym poprzednim przykładem i rozbijmy liczbę na pozycji (1,1) .

N.=[41210123)10101010]

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


Wyzwanie polega na tym, że biorąc pod uwagę listę pozycji i skończoną niepustą tablicę liczb naturalnych, zwraca postać rozstrzeloną po rozbiciu każdej liczby z listy pozycji.(x,y)


Przypadki testowe

Wkład: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]

Wydajność: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]


Wkład: Initial matrix: [[9, 8, 7], [8, 9, 7], [8, 7, 9]], numbers: [[0,0],[1,1],[2,2]]

Wydajność: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]


Wkład: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]

Wydajność: [[-9, 3],[3, 3]]


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

Wydajność: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]


Wkład: Initial Matrix: [[1]], numbers: [[0,0]]

Wydajność: [[1]]


Wkład: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]

Wydajność: [[1, 1, 4]]


Notatki

  • Zasady wejścia / wyjścia zastosowanie

  • Możesz założyć, że matryca wejściowa nigdy nie będzie pusta

  • Możesz założyć, że współrzędne zawsze będą poprawne

  • Współrzędna wejściowa w przypadkach testowych jest podawana jako (wiersz, kolumna). Jeśli potrzebujesz, aby to było (x, y), możesz zamienić wartości. Jeśli tak, proszę to zaznaczyć w swojej odpowiedzi


nowy w golfa; w jakim formacie próbka może pobrać te macierze? Dowolny format, który istnieje w języku? Forma łańcucha dokładnie tak, jak napisano?
rtpax

1
Proponuję dodać przypadek testowy dla matematycznych kwadratów.
Οurous

@Ourous, oh, oh, pisałem mój program, zakładając, że są kwadratowe, wracam do deski kreślarskiej, chyba
rtpax

Czy możemy założyć, że rozmiar matrycy wynosi co najmniej 2 na 2? Czy może też być wprowadzona matryca 1 na 1?
Kevin Cruijssen

@rtpax Dowolny format, chyba że pytanie stanowi inaczej, tak
tylko ASCII

Odpowiedzi:


9

C (GCC) 220 216 214 212 bajtów

kredyt na @ceilingcat za 2 bajty

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

Uruchom tutaj

nieco mniej golfowa wersja

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

Kod wywoławczy z przykładem

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

i wynik

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

11
Witamy w PPCG :)
Shaggy


7

JavaScript (ES7),  126 125 123  121 bajtów

Zaoszczędzono 2 bajty dzięki @Shaggy

Pobiera dane wejściowe jako (matrix)(list). Wyjścia poprzez modyfikację macierzy.

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

Wypróbuj online!

W jaki sposób?

(x,y)

  1. n
  2. m(x,y)/nq
  3. ponownie przejrzyj macierz, aby zaktualizować każdego sąsiada
  4. m(x,y)

Zamiast tego używamy funkcji rekurencyjnej, która wykonuje prostszy przepływ operacji, powtarzany tyle razy, ile potrzeba:

  1. n0
  2. n+1
  3. n
  4. zwiększ komórkę referencyjną (wszystkie kroki tego rodzaju są wykonywane kolejno po zakończeniu ostatniego wywołania rekurencyjnego)

Główną zaletą jest to, że potrzebujemy tylko jednej pętli nad matrycą. Drugą korzyścią jest to, że nie musimy obliczać żadnego ilorazu.

Przykład

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

Po kroku 1 w pierwszej iteracji , mamy:

M.=(1111271111) i n=9

A po kroku 2 w pierwszej iteracji :

M.=(1111171111)

-9+1

26

179

Po kroku 1 w drugiej iteracji , mamy:

M.=(2)2)2)2)182)2)2)2)) i n=9

A po kroku 2 w drugiej iteracji :

M.=(2)2)2)2)82)2)2)2))

8<9

Obecnie przyrost komórkę odniesienia, dwukrotnie ( w punkcie 4 na obu powtórzeń ), co prowadzi do wyniku końcowego:

M.=(2)2)2)2)102)2)2)2))

Skomentował

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
Możesz zaoszczędzić kilka bajtów, zastępując oba wystąpienia (0)2 backtickami.
Kudłaty

6

R , 163 162 161 159 155 146 bajtów

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}

Wypróbuj online!

Wyjaśnienie

(Odpowiada poprzedniej wersji kodu)

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

Czysty , 181 167 bajtów

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

Wypróbuj online!

W postaci częściowo zastosowanego literału funkcji.

Rozszerzony (pierwsza wersja):

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

Rdza - 295 bajtów

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

Jest to dość długi czas, ponieważ Rust wymaga indeksowania wektorów w liczbach całkowitych bez znaku, ale wymaga odejmowanych liczb całkowitych do odejmowania, co skutkuje ujemnymi. Jednak uważam, że mój algorytm jest jak dotąd „najkrótszym algorytmem”. W rzeczywistości nie ma potrzeby zajmowania się wykrywaniem krawędzi, dna itp.

Zauważ trzy rzeczy: po pierwsze, suma wszystkich komórek jest zawsze stała. Po drugie, jest to sytuacja podziału / reszty, więc możemy zastosować myślenie algorytmem Bresenhama. Po trzecie, pytanie zawsze dodaje tę samą liczbę do wszystkich komórek w pewnej odległości od komórki specjalnej pozycji, zanim zajmie się „dodatkowymi” rzeczami w specjalnej pozycji.

Algorytm:

Przechowuj oryginalną wartość komórki w pozycji P w M.

Rozpocznij pętlę:

Iteruj po każdej komórce I w macierzy. Jeśli pozycja komórki I mieści się w granicach 3 kwadrantu (odległość kwadratowa) od pozycji P, odejmij 1 od komórki P i dodaj 1 do komórki I. Policz, ile razy jest to wykonywane w jednej iteracji przez macierz.

Jeśli wartość pozostała w komórce w pozycji P jest mniejsza lub równa M / Count + M modulo Count, to przerwij pętlę. W przeciwnym razie wykonaj pętlę ponownie.

Powstała macierz będzie wersją rozłożoną na części. Count to w zasadzie sposób liczenia sąsiadów bez zajmowania się krawędziami. Pętla jest sposobem na rozbicie podziału / dodawania na powtarzające się pojedyncze dodawanie / odejmowanie jednego. Kontrola modulo zapewnia, że ​​pozostanie nam odpowiednia pozostała pozycja P, aby poradzić sobie z „eksplozjami”, które nie są równo podzielne między sąsiadami. Struktura pętli do / while umożliwia prawidłowe działanie P <0.

Wersja bez golfa na Rust Playground


1
Tak długa nazwa funkcji nie jest konieczna, jakikolwiek 1-bajtowy, tak jak fby to zrobił. Ale prawdopodobnie możesz zaoszczędzić jeszcze więcej bajtów, korzystając z anonimowej funkcji:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Kirill L.

3

Java 10, 194 193 191 190 184 182 171 bajtów

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

Iteracyjny port odpowiedzi JavaScript @Arnauld .
-17 bajtów dzięki @Arnauld .

Zmienia macierz wejściową zamiast zwracać nową, aby zapisać bajty.

Wypróbuj online.

Wyjaśnienie:

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 ok. Rzeczywiście pamiętałem, że poza granicami zwykle nie ma problemu w JS, ale rozumiem, dlaczego undefined[x]miałoby to zawieść. W każdym razie twój (x-X)**2+(y-Y)**2<3czek jest całkiem sprytny. Muszę pamiętać, że kiedy chcę sprawdzić wartości w macierzy w bloku 3x3 (i w granicach) wokół niego. Myślę, że faktycznie mam kilka takich odpowiedzi, w których teraz używam try-catch, a w jednym przypadku próbuję w końcu ... Spójrz na te, kiedy będę miał trochę czasu.
Kevin Cruijssen

1
171 bajtów z rozszerzonymi dla pętli.
Arnauld

@Arnauld Oh nice. Teraz, kiedy to widzę, nie mogę uwierzyć, że nie pomyślałem o tym, kiedy utworzyłem port z twojej odpowiedzi, ponieważ robisz to samo ..>.>;)
Kevin Cruijssen

2

Common Lisp , 498 bajtów

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

Wypróbuj online!

Użyj tej funkcji jako (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))

Wersja lepiej czytelna:

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

Przykład wyjściowy:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.