Explodierende Zahlen


25

Sandbox (gelöscht)

Definieren wir eine Matrix von 9s als:

N=[999999999]

Definieren wir eine explodierende Zahl als eine Zahl an Position , die in gleiche ganze Zahlen zwischen allen benachbarten Nachbarn (einschließlich sich selbst) zerlegt werden kann und deren absoluter Wert größer als 0 ist.(x,y)

Lassen Sie uns aus der vorherigen Matrix die Zahl an Position (0 indiziert) (1,1)

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

N=[10101010110101010]

Manchmal ist das Zerlegen des Ergebnisses in eine rationale Zahl größer als 1. Dies ist etwas, das wir beim Auflösen von Zahlen vermeiden müssen. In diesem Fall wird der Rest der explodierten Nummer zugewiesen.

Um dies zu demonstrieren, arbeiten wir weiter mit unserer vorherigen Matrix. Dieses Mal werden wir die Zahl an der Position explodieren(0,0)

N=[10101010110101010]

Hier haben wir 3 Nachbarn und die Nummer selbst. Hier ist die Gleichung was uns 2 für jede und 2 für den Rest gibt.10/4

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

N=[4121012310101010]

Manchmal ist eine Zahl auch nicht groß genug, um zu gleichen Teilen (wobei abs größer als 0 ist) zwischen seinen Nachbarn zerlegt zu werden (| rationale Zahl | <1). In diesen Fällen müssen wir von der explodierten Nummer "leihen" , um den Zustand "größer als 0" beizubehalten . Fahren wir mit unserem vorherigen Beispiel fort und explodieren die Zahl an Position .(1,1)

N=[4121012310101010]

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


Die Herausforderung besteht darin, bei einer Liste von Positionen und einem endlichen, nicht leeren Array von natürlichen Zahlen die aufgelöste Form zurückzugeben, nachdem jede Zahl aus der Positionsliste aufgelöst wurde.(x,y)


Testfälle

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

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


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

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


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

Ausgabe: [[-9, 3],[3, 3]]


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

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


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

Ausgabe: [[1]]


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

Ausgabe: [[1, 1, 4]]


Anmerkungen

  • Input / Output - Regeln gelten

  • Sie können davon ausgehen, dass die Eingabematrix niemals leer sein wird

  • Sie können davon ausgehen, dass Koordinaten immer gültig sind

  • Die Eingabekoordinate in Testfällen wird als (Zeile, Spalte) angegeben. Wenn Sie möchten, dass es (x, y) ist, können Sie die Werte austauschen. Wenn ja, geben Sie dies bitte in Ihrer Antwort an


Neu im Code Golf; In welchem ​​Format darf das Sample diese Matrizen aufnehmen? Gibt es ein Format in der Sprache? Stringform genau wie geschrieben?
RTPax

1
Ich schlage vor, einen Testfall für nicht quadratische Matrizen hinzuzufügen.
Donnerstag,

@Ourous uh oh, ich geschrieben hatte mein Programm vorausgesetzt , sie Platz zu sein garantiert wurden, zurück zum Reißbrett Ich denke
rtpax

Können wir annehmen, dass die Matrixgröße mindestens 2 mal 2 ist? Oder kann auch eine 1: 1-Matrix eingegeben werden?
Kevin Cruijssen

@rtpax Beliebiges Format, sofern in der Frage nicht anders angegeben, ja
ASCII

Antworten:


9

C (GCC) 220 216 214 212 Bytes

Gutschrift an @ceilingcat für 2 Bytes

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

Führen Sie es hier aus

eine etwas weniger golfene Version

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

Die Vorwahl mit einem Beispiel

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

und die Ausgabe

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

11
Willkommen bei PPCG :)
Shaggy


7

JavaScript (ES7),  126 125 123  121 Byte

2 Bytes dank @Shaggy gespart

Übernimmt die Eingabe als (matrix)(list). Ausgabe durch Ändern der Matrix.

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

Probieren Sie es online!

Wie?

(x,y)

  1. Gehen Sie durch die Matrix, um die Anzahl der Nachbarn zu berechnenn
  2. m(x,y)/nq
  3. Gehen Sie erneut durch die Matrix, um jeden Nachbarn zu aktualisieren
  4. m(x,y)

Stattdessen verwenden wir eine rekursive Funktion, die einen einfacheren Ablauf von Operationen ausführt und so oft wie nötig wiederholt:

  1. n0
  2. n+1
  3. n
  4. Inkrementieren der Referenzzelle (alle Schritte dieser Art werden nach Abschluss des letzten rekursiven Aufrufs nacheinander ausgeführt )

Der Hauptvorteil ist, dass wir nur eine Schleife über der Matrix benötigen. Der zweite Vorteil ist, dass wir überhaupt keinen Quotienten berechnen müssen.

Beispiel

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

Nach Schritt 1 der ersten Iteration haben wir:

M=(1111271111) und n=9

Und nach Schritt 2 der ersten Iteration :

M=(1111171111)

-9+1

26

179

Nach Schritt 1 der zweiten Iteration haben wir:

M=(2222182222) und n=9

Und nach Schritt 2 der zweiten Iteration :

M=(222282222)

8<9

Wir zählen nun die Referenzzelle zweimal ( Schritt 4 von beiden Iterationen ) zum Endergebnis führt:

M=(2222102222)

Kommentiert

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
Sie können ein paar Bytes sparen, indem Sie beide Vorkommen von (0)durch 2 Backticks ersetzen.
Shaggy

6

R , 163 162 161 159 155 146 Bytes

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}

Probieren Sie es online!

Erläuterung

(Entspricht einer früheren Version des Codes)

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

Sauber , 181 167 Bytes

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

Probieren Sie es online!

In Form eines teilweise angewendeten Funktionswörters.

Erweitert (erste Version):

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

Rust - 295 Bytes

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

Dies ist ziemlich lang, da Rust eine vorzeichenlose Ganzzahl-Indizierung von Vektoren erfordert, aber vorzeichenbehaftete Ganzzahlen zur Subtraktion benötigt, was zu Negativen führt. Ich glaube jedoch, dass mein Algorithmus der "kürzeste Algorithmus" ist. Es besteht eigentlich keine Notwendigkeit, Kanten, Boden usw. zu erkennen.

Beachten Sie drei Dinge: Erstens ist die Summe aller Zellen immer konstant. Zweitens ist dies eine Teilungs- / Rest-Situation, sodass wir das Denken nach dem Bresenham-Algorithmus anwenden können. Drittens fügt die Frage allen Zellen innerhalb eines bestimmten Abstands von der Sonderpositionszelle immer die gleiche Nummer hinzu, bevor das "zusätzliche" Zeug in der Sonderposition behandelt wird.

Algorithmus:

Speichern Sie den ursprünglichen Wert der Zelle an Position P in M.

Schleife beginnen:

Iteriere über jede Zelle I in der Matrix. Wenn die Position von Zelle I innerhalb von 3 Quadrance (Quadratabstand) von der Position P liegt, subtrahieren Sie 1 von Zelle P und addieren Sie 1 zu Zelle I. Zählen Sie, wie oft dies in einer Iteration durch die Matrix erfolgt.

Wenn der in der Zelle an Position P verbleibende Wert kleiner oder gleich M / Count + M modulo Count ist, unterbrechen Sie die Schleife. Führen Sie andernfalls die Schleife erneut durch.

Die resultierende Matrix wird die Explosionsversion sein. Count ist im Grunde eine Möglichkeit, Nachbarn zu zählen, ohne mit Kanten umzugehen. Looping ist ein Weg, um das Teilungs- / Additionsmaterial in eine wiederholte einzelne Addition / Subtraktion von eins zu zerlegen. Der Modulo-Check stellt sicher, dass an Position P noch der Rest für Explosionen übrig ist, die sich nicht gleichmäßig auf die Nachbarn aufteilen lassen. Die do / while-Schleifenstruktur ermöglicht, dass P <0 ordnungsgemäß funktioniert.

Ungolfed-Version auf dem Rostspielplatz


1
Ein so langer Funktionsname ist nicht erforderlich, wie es bei einem 1-Byte-Namen der Fall fwäre. Aber Sie könnten wahrscheinlich noch mehr Bytes sparen, indem Sie eine anonyme Funktion verwenden:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Kirill L.

3

Java 10, 194 193 191 190 184 182 171 Bytes

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

Iterativer Port der JavaScript-Antwort von @Arnauld .
-17 Bytes dank @Arnauld .

Ändert die Eingabematrix, anstatt eine neue zurückzugeben, um Bytes zu sparen.

Probieren Sie es online aus.

Erläuterung:

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. Ich erinnere mich zwar, dass es in JS normalerweise kein Problem gibt, aber ich kann verstehen, warum undefined[x]dies fehlschlagen würde. Wie auch immer, Ihr (x-X)**2+(y-Y)**2<3Scheck ist ziemlich schlau. Denken Sie daran, wenn ich jemals Werte in einer Matrix in einem 3x3-Block (und innerhalb von Grenzen) überprüfen möchte. Ich denke, ich habe tatsächlich ein paar Antworten wie diese, bei denen ich jetzt einen Try-Catch verwende und in einem Fall schließlich versuche. Werde mir diese ansehen, wenn ich etwas Zeit habe.
Kevin Cruijssen

1
171 Bytes mit erweiterten for-Schleifen.
Arnauld

@ Arnauld Oh schön. Jetzt wo ich es sehe, kann ich nicht glauben, dass ich nicht darüber nachgedacht habe, als ich aus Ihrer Antwort einen Port erstellt habe, da Sie dasselbe tun ..>.>;)
Kevin Cruijssen

2

Common Lisp , 498 Bytes

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

Probieren Sie es online!

Verwenden Sie diese Funktion als (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))

Besser lesbare Version:

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

Ausgabebeispiel:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.