Renverser le tas de sable

12

(Il existe des questions connexes sur les tas de sable infinis et sur la recherche d'éléments d'identité des tas de sable .)

Étant donné une matrice d'entiers non négatifs, renvoyez une matrice de mêmes dimensions, mais renversée :

  1. Si la matrice ne contient aucune valeur supérieure à 4, renvoyez-la.
  2. Chaque "cellule" supérieure à 3 est réduite de 4, et toutes les cellules directement voisines (au-dessus, en dessous, à gauche et à droite) sont incrémentées, si elles existent.
  3. GOTO 1.

Exemples:

0 1 0        0 2 0
2 4 0   ->   3 0 1
0 0 3        0 1 3

1 2 3    2 3 4    2 5 1    4 1 2    0 3 3    0 3 3    0 3 3
4 5 6 -> 2 4 4 -> 4 2 3 -> 0 5 4 -> 3 2 1 -> 3 3 1 -> 3 3 2
7 8 9    5 7 7    2 6 5    4 3 2    0 5 3    1 1 4    1 2 0

(Il vous suffit de renvoyer le résultat final. Le chemin sur lequel vous l'atteignez peut différer de celui illustré ici: peu importe l'ordre dans lequel vous effectuez les opérations de basculement, ils conduisent tous au même résultat.)

Pour une explication plus approfondie et une motivation, voir cette vidéo Numberphile ou l'article Wikipedia sur le modèle de tas de sable abélien .

Règles:

  • Vous pouvez prendre des entrées et des sorties de n'importe quelle manière standard
  • Les échappatoires sont interdites
  • L'entrée et la sortie peuvent être:
    • une liste imbriquée: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    • une liste simple: [1, 2, 3, 4, 5, 6, 7, 8, 9]et la forme
    • une sorte de type de matrice native
    • une chaîne, par exemple 1 2 3\n4 5 6\n7 8 9
    • ou tout ce qui fonctionne dans votre langue.
  • L'entrée et la sortie doivent être sous la même forme
  • L'entrée peut contenir des nombres plus grands que ceux indiqués ici, mais la taille peut être limitée par les limites de votre langue (équivalents MAXINT, le cas échéant)
  • La matrice peut avoir n'importe quelle forme (par exemple 1x1, 2x2, 3x3, 4x4, 2x7, 11x3, ...)
  • Vous n'avez pas besoin de gérer le cas où la forme est 0xN ou Nx0.

Cas de test

[[2, 5, 4], [8, 6, 4], [1, 2, 3]] -> [[3, 3, 0], [1, 2, 2], [1, 3, 2]]
[[0, 0, 2], [1, 3, 3], [0, 0, 0]] -> [[0, 0, 2], [1, 3, 3], [0, 0, 0]]
[[9, 9, 9], [9, 9, 9], [9, 9, 9]] -> [[1, 3, 1], [3, 1, 3], [1, 3, 1]]
[[4, 5], [2, 3]] -> [[2, 3], [0, 1]]
[[2, 3, 5], [2, 2, 0]] -> [[3, 0, 2], [2, 3, 1]]
[[7]] -> [[3]]

C'est , le code le plus court (par langue) l'emporte.

L3viathan
la source
Peut-on afficher tous les résultats intermédiaires?
feersum
@feersum Je suppose que oui, tant qu'il est clair quel est le résultat final.
L3viathan

Réponses:

8

MATL , 17 octets

tss:"t3>t1Y6Z+w4*-+

Essayez-le sur MATL Online! Ou vérifiez tous les cas de test .

Explication

Le programme répète autant de fois que la somme de l'entrée. Il s'agit d'une limite supérieure lâche sur le nombre d'itérations requis.

Pour chaque itération, des entrées dans la matrice de tas de sable dépassant 3sont détectées, donnant une matrice de 1et 0, qui est convolue avec le masque à 4 voisins. Les entrées dépassant 3dans la matrice de tas de sable sont réduites de 4, et le résultat de la convolution est ajouté.

Pour les dernières itérations, dans lesquelles la matrice de tas de sable n'a pas de nombres dépassant 3, des zéros sont soustraits et ajoutés à elle, de sorte qu'elle n'est pas affectée.

t       % Implicit input (matrix). Duplicate
ss      % Sum of matrix entries
:"      % Repeat that many times
  t     %   Duplicate
  3>    %   True for matrix entries that exceed 3
  t     %   Duplicate
  1Y6   %   Push predefined literal [0, 1, 0; 1, 0, 1; 0, 1, 0]
  Z+    %   2D convolution, keeping size
  w     %   Swap
  4*    %   Multiply by 4
  -     %   Subtract
  +     %   Add
        % Implicit end. Implicit display
Luis Mendo
la source
3
Convolution élevée cinq.
Martin Ender
@MartinEnder Ah, vous l'avez également utilisé :-) Ravi de voir un autre convoluteur! Je suis sûr que Flawr nous rejoindra bientôt
Luis Mendo
2
@LuisMendo Convolutionista
Suever
4

Mathematica, 65 octets

#//.s_:>s+ListConvolve[{v={0,1,0},1-v,v},x=UnitStep[s-4],2,0]-4x&

Explication

#//.s_:>...&

Transformez à plusieurs reprises l'entrée en renversant toutes les piles supérieures à 3. Ce processus s'arrête automatiquement lorsque la transformation ne parvient pas à changer la matrice (c'est-à-dire lorsqu'il n'y a plus de grandes piles). Dans l'expression suivante, la matrice est appelée s.

...x=UnitStep[s-4]...

Créez une matrice qui a un 1chaque fois que la matrice actuelle a un 4ou plus et un zéro sinon. Il s'agit essentiellement d'un masque qui indique quelles piles doivent être renversées. Appelle le masque x.

ListConvolve[{v={0,1,0},1-v,v},x=UnitStep[s-4],2,0]

D'abord, nous calculons le nombre de sable ajouté à chaque tas en raison des tas voisins renversés. Cela se fait avec une convolution de la matrice suivante sur x:

0 1 0
1 0 1
0 1 0

Essentiellement, il en ajoute un à la cellule actuelle pour chacun de ses voisins von-Neumann dans le masque.

s+...-4x

Nous ajoutons le résultat précédent à s, puis nous en soustrayons quatre fois le masque pour réduire les piles renversées.

Martin Ender
la source
3

Octave, 65 octets

Cela ne semble pas très bon, il me manque des trucs ...

m=input(0);do;m+=conv2(m>3,[0 1 0;1 -4 1;0 1 0],"same")
until m<4
feersum
la source
Quelle version d'Octave utilisez-vous qui permet input(0)?
Suever
@Suever>> version ans = 4.0.1
feersum
2

JavaScript (ES6), 101 95 octets

Prend la largeur de la matrice wet un tableau de valeurs adans la syntaxe de curry (w)(a). Renvoie un tableau de valeurs.

w=>g=a=>(b=a.map((n,i)=>n%4+(F=d=>~m|i%w&&a[i+d]>>2)(m=w)+F(-w)+F(m=-1)+F(!++i)))+0==a+0?a:g(b)

Formaté et commenté

w =>                      // main function: takes w as input, returns g
  g = a =>                // recursive function g: takes a as input
    (                     //
      b = a.map((n, i) => // for each element n at position i in a:
        n % 4 + (         //   keep only n MOD 4
          F = d =>        //   define F(): function that takes d as input
            ~m |          //     if m is not equal to -1
            i % w &&      //     or i MOD w is not null:
            a[i + d] >> 2 //       return a fourth of the value of the cell at i + d
        )(m = w) +        //   test the cell below the current cell
        F(-w) +           //   test the cell above
        F(m = -1) +       //   test the cell on the left
        F(!++i)           //   test the cell on the right
      )                   // end of map(): assign the result to b
    ) + 0 == a + 0 ?      // if b is equal to a:
      a                   //   stop recursion and return a
    :                     // else:
      g(b)                //   do a recursive call with b

Cas de test

Arnauld
la source
1

JavaScript (ES6), 118 114 104 octets

Sauvegardé 2 octets grâce à @Neil

f=a=>a.find(b=>++y&&b.find(c=>++x&&c>3,x=0),y=0)?f(a.map(b=>b.map(c=>c+=--i|y?i*i+y*y==1:-4,i=x,--y))):a
ETHproductions
la source
Ça (i-=x)|y-j?i*i+aide?
Neil
@Neil Oui, merci!
ETHproductions
... J'étais au téléphone mais je pensais aussi a.find(...b.find(...c>3&&a.map(...)))&&f(a).
Neil
@Neil Je ne pense pas que cela fonctionnerait, car .mapne mute pas ...
ETHproductions
Il semble que le faire muter coûte un peu moins cher que de déplacer la carte à l'intérieur de la découverte sauve:f=a=>a.find((b,x)=>b.find((c,y)=>c>3&&a.map(b=>b.map((_,j)=>b[j]+=x|(j-=y)?x*x+j*j==1:-4)&x--)))&&f(a)
Neil
1

C ++, 261 258 250 octets

#import<vector>
#define S size()
void f(std::vector<std::vector<int>>&m){s:int i,j,r;for(i=r=0;i<m.S;++i)for(j=0;j<m[i].S;++j){if(m[i][j]>3){r=1;m[i][j]-=4;j>0&&m[i][j-1]++;i>0&&m[i-1][j]++;j<m[i].S-1&&m[i][j+1]++;i<m.S-1&&m[i+1][j]++;}}if(r)goto s;}

Prend l'entrée comme référence à un vecteur de vecteurs et le modifie directement.

Essayez-le en ligne!

Steadybox
la source