Exploser des nombres


25

bac à sable (supprimé)

Permet de définir une matrice de 9 comme:

N=[999999999]

Permet de définir un nombre qui explose comme un nombre à la position (x,y) qui peut être décomposé en entiers égaux entre tous ses voisins adjacents (y compris lui-même) et la valeur absolue de chaque partie est supérieure à 0.

De la matrice précédente, permet d'exploser le nombre à la position (1,1) (0 indexé)

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

N=[10101010110101010]

Parfois, décomposer le résultat en un nombre rationnel supérieur à 1. C'est quelque chose que nous devons éviter lors de l'explosion des nombres. Dans ce cas, le reste sera affecté au numéro éclaté.

Pour le démontrer, continuons à travailler avec notre matrice précédente. Cette fois, nous allons exploser le nombre en position(0,0)

N=[10101010110101010]

Ici, nous avons 3 quartiers et le numéro lui-même. Ici , l'équation est quelque chose comme 10/4 qui nous donnent 2 pour chacun et 2 en reste.

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

N=[4121012310101010]

De plus, parfois un nombre ne sera pas assez grand pour être décomposé en parties égales (où l'abs est supérieur à 0) entre ses voisins (| nombre rationnel | <1). Dans ce cas, nous devons "emprunter" au nombre éclaté afin de maintenir la condition "supérieur à 0" . Continuons avec notre exemple précédent et explosons le nombre à la position (1,1) .

N=[412dix123dixdixdixdix]

N=[4+112+1dix+112+10+1-6dix+1dix+1dix+1dix+1]
N=[5131113-511111111]


Le défi est, étant donné une liste de positions (X,y) et un tableau fini non vide de nombres naturels, de renvoyer la forme éclatée après que chaque nombre de la liste de positions a été éclaté.


Cas de test

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

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


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

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


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

Sortie: [[-9, 3],[3, 3]]


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

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


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

Sortie: [[1]]


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

Sortie: [[1, 1, 4]]


Remarques

  • Les règles d'entrée / sortie s'appliquent

  • Vous pouvez supposer que la matrice d'entrée ne sera jamais vide

  • Vous pouvez supposer que les coordonnées seront toujours valides

  • La coordonnée d'entrée dans les cas de test est donnée sous la forme (ligne, colonne). Si vous en avez besoin (x, y), vous pouvez échanger les valeurs. Si oui, veuillez l'indiquer dans votre réponse


nouveau au code golf; Dans quel format l'échantillon peut-il prendre ces matrices? Un format qui existe dans la langue? Forme de chaîne exactement comme écrite?
rtpax

1
Je suggère d'ajouter un cas de test pour les matricules non carrées.
Οurous

@Nos uh oh, j'avais écrit mon programme en supposant qu'ils étaient garantis carrés, de retour à la planche à dessin, je suppose
rtpax

Pouvons-nous supposer que la taille de la matrice est d'au moins 2 par 2? Ou une matrice 1 par 1 peut-elle également être entrée?
Kevin Cruijssen

@rtpax N'importe quel format sauf indication contraire de la question, oui
ASCII uniquement

Réponses:


9

C (GCC) 220 216 214 212 octets

crédit à @ceilingcat pour 2 octets

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

Exécutez-le ici

une version légèrement moins golfée

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

Le code appelant avec un exemple

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

et la sortie

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

11
Bienvenue à PPCG :)
Shaggy


7

JavaScript (ES7),  126 125 123  121 121 octets

Sauvegardé 2 octets grâce à @Shaggy

Prend l'entrée comme (matrix)(list). Sorties en modifiant la matrice.

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

Essayez-le en ligne!

Comment?

(X,y)

  1. n
  2. m(X,y)/nq
  3. parcourir à nouveau la matrice pour mettre à jour chaque voisin
  4. m(X,y)

Au lieu de cela, nous utilisons une fonction récursive qui exécute un flux d'opérations plus simple, répété autant de fois que nécessaire:

  1. n0
  2. n+1
  3. n
  4. incrémenter la cellule de référence (toutes les étapes de ce type sont exécutées successivement lorsque le dernier appel récursif est terminé)

Le principal avantage est que nous n'avons besoin que d'une boucle sur la matrice. Le deuxième avantage est que nous n'avons pas du tout à calculer de quotient.

Exemple

M=(0000260000) et (X,y)=(1,1)

Après l' étape 1 de la première itération , nous avons:

M=(1111271111) et n=9

Et après l' étape 2 de la première itération :

M=(1111171111)

-9+1

26

17 est supérieur à 9, nous faisons un appel récursif.

Après l' étape 1 de la deuxième itération , nous avons:

M=(2222182222) et n=9

Et après l' étape 2 de la deuxième itération :

M=(222282222)

Étape 3 de la deuxième itération : cette fois, nous avons8<9, nous nous arrêtons donc là.

Nous incrémentons maintenant la cellule de référence deux fois ( étape 4 des deux itérations ), conduisant au résultat final:

M=(2222dix2222)

Commenté

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
Vous pouvez économiser quelques octets en remplaçant les deux occurrences de (0)par 2 backticks.
Shaggy

6

R , 163 162 161 159 155 155 146 octets

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}

Essayez-le en ligne!

Explication

(Correspond à une version précédente du code)

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

Nettoyer , 181 167 octets

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

Essayez-le en ligne!

Sous la forme d'un littéral de fonction partiellement appliqué.

Développé (première 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

Rouille - 295 octets

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

Ceci est assez long car Rust nécessite une indexation entière non signée des vecteurs, mais oblige les entiers signés à effectuer une soustraction entraînant des négatifs. Cependant, je crois que mon algorithme est jusqu'à présent "l'algorithme le plus court". Il n'y a en fait pas besoin de gérer la détection des bords, du fond, etc.

Remarquez trois choses: premièrement, la somme de toutes les cellules est toujours constante. Deuxièmement, il s'agit d'une situation de division / reste, nous pouvons donc appliquer la pensée de style algorithme de Bresenham. Troisièmement, la question ajoute toujours le même nombre à toutes les cellules situées à une certaine distance de la cellule de position spéciale, avant de traiter les éléments "supplémentaires" dans la position spéciale.

Algorithme:

Stockez la valeur d'origine de la cellule à la position P dans M.

Commencer la boucle:

Itérer sur chaque cellule I de la matrice. Si la position de la cellule I est à moins de 3 quadrances (distance au carré) de la position P, soustrayez 1 de la cellule P et ajoutez 1 à la cellule I. Comptez combien de fois cela est fait en une seule itération à travers la matrice.

Si la valeur restante dans la cellule à la position P est inférieure ou égale à M / Count + M modulo Count, alors rompez la boucle. Sinon, recommencez la boucle.

La matrice résultante sera la version éclatée. Le comptage est essentiellement un moyen de compter les voisins sans traiter les bords. Le bouclage est un moyen de décomposer la substance de division / addition en une seule addition / soustraction répétée d'une seule. Le contrôle modulo garantit que nous aurons le reste approprié à la position P pour faire face aux «explosions» qui ne sont pas également réparties entre les voisins. La structure de boucle do / while permet à P <0 de fonctionner correctement.

Version non golfée sur le terrain de jeu de Rust


1
Un nom de fonction aussi long n'est pas nécessaire, comme 1 octet f. Mais vous pourriez probablement économiser encore plus d'octets, en utilisant une fonction anonyme:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
Kirill L.

3

Java 10, 194 193 193 191 190 184 182 171 octets

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 itératif de la réponse JavaScript de @Arnauld .
-17 octets grâce à @Arnauld .

Modifie la matrice d'entrée au lieu d'en renvoyer une nouvelle pour économiser des octets.

Essayez-le en ligne.

Explication:

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] avec yhors des limites est OK en JS (donnant un indéfini ), mais m[y][x]avecy hors limites se bloquerait également.
Arnauld

@Arnauld Ah ok. Je me suis en effet souvenu que les limites n'étaient généralement pas un problème dans JS, mais je peux comprendre pourquoi undefined[x]échouerait. Quoi qu'il en soit, votre (x-X)**2+(y-Y)**2<3chèque est assez intelligent. Besoin de me rappeler que lorsque je veux vérifier des valeurs dans une matrice dans un bloc 3x3 (et dans des limites) autour d'elle. Je pense que j'ai en fait quelques réponses comme ça, où j'utilise maintenant un try-catch, et dans un cas, j'essaye enfin .. Je les examinerai quand j'aurai du temps.
Kevin Cruijssen

1
171 octets avec boucles améliorées.
Arnauld

@Arnauld Oh gentil. Maintenant que je le vois, je ne peux pas croire que je n'avais pas pensé à cela quand j'ai créé un port à partir de votre réponse, puisque vous faites de même ..>.>;)
Kevin Cruijssen

2

Lisp commun , 498 octets

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

Essayez-le en ligne!

Utilisez cette fonction comme (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))

Meilleure version lisible:

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

Exemple de sortie:

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.