Rovescia la catasta di sabbia


12

(Ci sono domande correlate su infinite sandpiles e sulla ricerca di elementi di identità di sandpiles .)

Data una matrice di numeri interi non negativi, restituisce una matrice delle stesse dimensioni, ma rovesciata :

  1. Se la matrice non contiene valori superiori a 4, restituirla.
  2. Ogni "cella" più grande di 3 viene ridotta di 4 e tutte le celle direttamente vicine (sopra, sotto, sinistra e destra) vengono incrementate, se esistono.
  3. GOTO 1.

Esempi:

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

(Devi solo restituire il risultato finale. Il percorso su cui lo raggiungi potrebbe differire da quello mostrato qui: non importa in quale ordine esegui le operazioni di rovesciamento, portano tutti allo stesso risultato.)

Per una spiegazione più approfondita e un po 'di motivazione, guarda questo video di Numberphile o l'articolo di Wikipedia sul modello di sandpile abeliano .

Regole:

  • È possibile accettare input e output in uno dei modi standard
  • Le scappatoie sono vietate
  • Input e output possono essere:
    • un elenco nidificato: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    • un semplice elenco: [1, 2, 3, 4, 5, 6, 7, 8, 9]e la forma
    • qualche tipo di matrice nativa
    • una stringa, ad es 1 2 3\n4 5 6\n7 8 9
    • o qualsiasi altra cosa funzioni nella tua lingua.
  • L'input e l'output devono essere nella stessa forma
  • L'input può contenere numeri più grandi di quelli mostrati qui, ma la dimensione potrebbe essere limitata dai limiti della tua lingua (equivalenti MAXINT, se applicabile)
  • La matrice può avere qualsiasi forma (ad es. 1x1, 2x2, 3x3, 4x4, 2x7, 11x3, ...)
  • Non è necessario gestire il caso in cui la forma è 0xN o Nx0.

Casi 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]]

Questo è , il codice più breve (per lingua).


È corretto visualizzare tutti i risultati intermedi?
feersum

@feersum Immagino di sì, purché sia ​​chiaro quale sia il risultato finale.
L3viathan,

Risposte:


8

MATL , 17 byte

tss:"t3>t1Y6Z+w4*-+

Provalo su MATL Online! Oppure verifica tutti i casi di test .

Spiegazione

Il programma scorre più volte la somma dell'input. Questo è un limite superiore libero sul numero richiesto di iterazioni.

Per ogni iterazione, 3vengono rilevate voci nella matrice di sandpile in eccesso , dando una matrice di 1e 0, che è contorta con la maschera a 4 vicini. Le voci eccedenti 3nella matrice della pila di sabbia vengono ridotte di 4e viene aggiunto il risultato della convoluzione.

Per le ultime iterazioni, in cui la matrice della sandpile non ha numeri superiori 3, gli zeri vengono sottratti e aggiunti ad esso, quindi non viene influenzato.

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

3
Convoluzione alta cinque.
Martin Ender,

@MartinEnder Ah, l'hai usato anche tu :-) Bello vedere un collega convoluter! Sono sicuro che Flawr si unirà a noi presto
Luis Mendo il

2
@LuisMendo Convolutionista
Suever

4

Mathematica, 65 byte

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

Spiegazione

#//.s_:>...&

Trasforma ripetutamente l'input rovesciando tutte le pile maggiori di 3. Questo processo si interrompe automaticamente quando la trasformazione non cambia la matrice (cioè quando non esistono più pile grandi). Nell'espressione seguente viene chiamata la matrice s.

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

Crea una matrice che ha una 1ogni volta che la matrice corrente ha una 4o maggiore e uno zero altrimenti. Questa è essenzialmente una maschera che indica quali pile devono essere rovesciate. Chiama la maschera x.

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

Per prima cosa calcoliamo il numero di sabbia che viene aggiunto a ciascuna pila a causa di pile vicine rovesciate. Questo viene fatto con una convoluzione della seguente matrice sopra x:

0 1 0
1 0 1
0 1 0

In sostanza, ne aggiunge uno alla cella corrente per ciascuno dei suoi vicini von-Neumann nella maschera.

s+...-4x

Aggiungiamo il risultato precedente se quindi sottraggiamo quattro volte la maschera da esso per ridurre le pile rovesciate.


3

Ottava, 65 byte

Questo non sembra molto buono, devo mancare alcuni trucchi ...

m=input(0);do;m+=conv2(m>3,[0 1 0;1 -4 1;0 1 0],"same")
until m<4

Quale versione di Octave stai utilizzando per consentire input(0)?
Suever,

@Suever>> version ans = 4.0.1
feersum

2

JavaScript (ES6), 101 95 byte

Accetta la larghezza della matrice we una matrice di valori anella sintassi del curry (w)(a). Restituisce una matrice di valori.

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)

Formattato e commentato

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

Casi test


1

JavaScript (ES6), 118 114 104 byte

Salvato 2 byte grazie a @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

Does (i-=x)|y-j?i*i+aiuto?
Neil,

@Neil Lo fa davvero, grazie!
ETHproductions

... Ero al telefono ma stavo anche considerando a.find(...b.find(...c>3&&a.map(...)))&&f(a).
Neil,

@Neil Non penso che funzionerebbe, dal momento .mapche non
muta

Sembra che la sua mutazione abbia un costo leggermente inferiore rispetto allo spostamento della mappa all'interno del salvataggio: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 byte

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

Prende l'input come riferimento a un vettore di vettori e lo modifica direttamente.

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.