Espansione batterica


25

Le colonie di batteri etichettati 1attraverso 9vivono su un segmento di cellule equidistanti, con le cellule vuote indicate da0

0 0 2 0 0 0 1 2 0 0 3 3 0 0

Ogni secondo, ogni colonia si diffonde nelle celle vuote adiacenti. Se due colonie raggiungono una cella vuota contemporaneamente, la colonia con l'etichetta più grande la prende.

t=0:  0 0 2 0 0 0 1 2 0 0 3 3 0 0
t=1:  0 2 2 2 0 1 1 2 2 3 3 3 3 0
t=2:  2 2 2 2 2 1 1 2 2 3 3 3 3 3  

Le colonie non possono diffondersi oltre i confini. Una colonia non viene mai sostituita da un'altra colonia, quindi una volta riempite tutte le celle vuote, nulla cambia più.

Dato lo stato iniziale, visualizza o stampa lo stato finale. Utilizzare un elenco ragionevole o un formato stringa. Non si dovrebbero generare stati intermedi. L'input conterrà almeno una colonia batterica.

Correlati: coprire gli zeri in un elenco . (Le colonie si diffondono solo a destra.)

Casi di prova: uscita sotto input.

0 0 2 0 0 0 1 2 0 0 3 3 0 0
2 2 2 2 2 1 1 2 2 3 3 3 3 3

7 0 3 0 0 0 0 0 8 0 9 1
7 7 3 3 3 8 8 8 8 9 9 1

5 0 3 0 0 0
5 5 3 3 3 3

7 7 1
7 7 1

1 0 1
1 1 1

Risposte:


14

JavaScript (ES6), 66 62 byte

a=>a.map(_=>a=a.map((c,i)=>c||Math.max(a[i-1]|0,a[i+1]|0)))&&a

Spiegazione

a=>                 // a = input as array of numbers
  a.map(_=>         // loop for the length of a, this ensures the end is always reached
    a=a.map((c,i)=> // update a after to the result of t, for each cell c of index i
      c||           // keep the cell if it is not 0
        Math.max(   // else set the cell to the max value of:
          a[i-1]|0, //     the previous cell (or 0 if i - 1 less than 0),
          a[i+1]|0  //     or the next cell (or 0 if i + 1 greater than the length of a)
        )
    )
  )
  &&a               // return a

Test


10

Pyth, 18 byte

um|@d1eSd.:++0G03Q

Suite di test

Prende l'input come un elenco di numeri interi.

Essenzialmente, questa utilizza un applicano until convergenza u. Applica l'aggiornamento formando tutti gli elenchi di ciascuna cella e le due celle su entrambi i lati, quindi aggiornando ogni cella azzerata al massimo dei suoi vicini.

um|@d1eSd.:++0G03Q
                      Implicit: Q = eval(input())
u                Q    Apply the following until convergence, starting with G = Q.
           ++0G0      Pad G with zeros on either side.
         .:     3     Form all 3 element substrings.
                      Now, for each element of G, we have a list of the form
                      [previous, current, next]
 m                    Map over this list
  |@d1                The current element, if it's nonzero
      eSd             Else the max of the list.

8

Mathematica, 77 byte

Non molto competitivo rispetto alla //.soluzione di alephalpha , ma ho pensato che una sfida di dovrebbe avere una CellularAutomatonrisposta:

CellularAutomaton[{If[#2<1,Max@##,#2]&@@#&,{},1},{#,0},{{{l=Length@#}},l-1}]&

La funzione accetta una tonnellata di parametri ... diamo loro alcuni nomi:

CellularAutomaton[{f,n,r},{i,b},{{{t}},d}]

Ecco cosa fanno:

  • rè l'intervallo della regola, ovvero determina quanti vicini vengono considerati per l'aggiornamento. Vogliamo un vicino per ogni lato, quindi usiamo1 .
  • nè normalmente il numero o l'elenco dei colori (diversi tipi di celle), ma se specifichiamo la regola come funzione personalizzata anziché come numero di regola, questo dovrebbe essere {}.
  • fè una funzione che determina la regola di aggiornamento. Prende un elenco di 3 celle (se r = 1) e restituisce il nuovo colore per la cella centrale.
  • iè la condizione iniziale. Questo è l'input.
  • bè lo sfondo. In caso contrario, CellularAutomatonutilizza i limiti periodici, che non desideriamo. L'uso invece 0impone una condizione di confine morta.
  • tè il numero di volte da simulare. Non abbiamo bisogno di più passaggi di quanto l'input sia ampio, perché in seguito i batteri si saranno convertiti, quindi t = Length@#. Normalmente, CellularAutomatonrestituisce tutti i passaggi intermedi. Possiamo evitarlo avvolgendo tdue elenchi.
  • ddetermina quali celle sono presentate nell'output. Per impostazione predefinita, otterremmo tutte le celle che potrebbero essere potenzialmente interessate dalla regola (che è t*rcelle aggiuntive su entrambe le estremità dell'input). Lo diamo l-1, perché questa è una delle poche situazioni in Mathematica in cui viene utilizzato un indice a base zero.

6

Haskell, 86 83 81 79 73 71 byte

(0#r)l=max r l
(o#_)_=o
p!_=zipWith3(#)p(0:p)$tail p++[0] 
id>>=foldl(!)

Esempio di utilizzo: id>>=foldl(!) $ [7,0,3,0,0,0,0,0,8,0,9,1]-> [7,7,3,3,3,8,8,8,8,9,9,1].

Non c'è molto da spiegare: se una cella è 0, prendi il massimo degli elementi vicini. Ripeti i tempi di lunghezza dell'input. Per questo ho ripetuto xvia foldlma ignoro il secondo argomento inp .

Modifica: @Mauris ha trovato 6 byte da salvare e @xnor altri due. Grazie!


È possibile sostituire h pcon p!_quindi sostituire (const.h)con (!)per salvare 6 byte.
Lynn,

@Mauris: intelligente. Molte grazie!
nimi,

@nimi Penso che l'ultima riga sia anonima id>>=foldl(!).
xnor

@xnor: sì, lo fa! Ben individuato!
nimi

4

CJam, 27 24 byte

{_,{0\0++3ew{~@e>e|}%}*}

Provalo qui.

Questo spinge un blocco senza nome che trasforma un elenco nello stack in un nuovo elenco.

Spiegazione

_,       e# Duplicate the input and get its length N.
{        e# Run this block N times (convergence won't take that long)...
  0\0++  e#   Wrap the list in two zeroes.
  3ew    e#   Get all sublists of length 3.
  {      e#   Map this block onto each sublist...
    ~    e#     Dump all three elements on the stack.
    @    e#     Pull up the left neighbour.
    e>   e#     Maximum of both neighbours.
    e|   e#     Logical OR between centre cell and maximum of neighbours.
  }%
}*

La convergenza laterale è un bel trucco
Luis Mendo il

1
... che ho preso spudoratamente in prestito :-)
Luis Mendo il

4

J, 24 23 byte

(+=&0*(0,~}.)>.0,}:)^:_

Uso:

   ((+=&0*(0,~}.)>.0,}:)^:_) 0 1 5 0 0 0 6
1 1 5 5 6 6 6

Il metodo è simile alla soluzione di Mauris .

(                  )^:_ repeat until change
               0,}:     concat 0 and tailless input
      (0,~}.)           concat headless input and 0
             >.         elementwise maximum of the former two lists
  =&0*                  multiply by input_is_0 (zeroing out the list at nonzero input positions)
 +                       add to input

Provalo online qui.

1 byte salvato grazie a Zgarb.


3

Mathematica, 77 74 66 62 byte

Risparmiato 12 byte grazie a Martin Büttner.

#//.i_:>BlockMap[If[#2<1,Max@##,#2]&@@#&,Join[{0},i,{0}],3,1]&

3

J, 33 byte

3 :'y+(y=0)*>./(_1,:1)|.!.0 y'^:_

Un po 'più di quanto mi sarebbe piaciuto.

3 :'                         '^:_   Repeat a "lambda" until a fixed point:
                            y         The input to this lambda.
               (_1,:1)|.!.0           Shift left and right, fill with 0.
            >./                       Maximum of both shifts.
      (y=0)*                          Don't grow into filled cells.
    y+                                Add growth to input.

È così diverso da quello che ho, penso che dovresti pubblicarlo come risposta :)
Lynn,

3

Python 3.5, 83 byte

Questa funzione accetta un elenco di numeri interi Python. Non sono sicuro che rimanga molto da giocare a golf, ma mi piacerebbe almeno renderlo competitivo con un'altra lingua!

def b(s):
 for _ in s:s=[s[n]or max((0,*s)[n:n+3])for n in range(len(s))]
 return s

Da Python 3.5, PEP 448 ci consente di spacchettamento sin 0,*s. Le versioni precedenti richiedono un byte in più, in questo modo:

def b(s):
 for _ in s:s=[s[n]or max(([0]+s)[n:n+3])for n in range(len(s))]
 return s

Ringraziamo la soluzione e la spiegazione di user81655 per avermi aiutato a capire che non ho bisogno di testare se l'elenco ha smesso di cambiare; Ho solo bisogno di ripetere abbastanza volte per essere sicuro che tutti gli zero debbano essere stati coperti. (Il numero massimo di iterazioni necessarie è uno in meno della lunghezza dell'elenco; ciò comporta un'iterazione in più rispetto a quella, perché richiede meno codice.)


@ChrisH: Non funziona su Python 3.5, e non credo che avrebbe funzionato con le versioni precedenti sia: non fa che spostare il returndi dentro il for _ in sciclo?
Tim Pederick,

commento eliminato - mi è capitato di provare solo i casi di test che si risolvono per la prima volta.
Chris H,

3

Matlab, 90 byte

Che ne dici di alcune convoluzioni?

x=input('');for n=x;x=x+max(conv(x,[0 0 1],'same'),conv(x,[1 0 0],'same')).*~x;end;disp(x)

Esempio

>> x=input('');for n=x;x=x+max(conv(x,[0 0 1],'same'),conv(x,[1 0 0],'same')).*~x;end;disp(x)
[7 0 3 0 0 0 0 0 8 0 9 1]
     7     7     3     3     3     8     8     8     8     9     9     1

3

Haskell, 66 65 byte

f x=[maximum[[-j*j,a]|(j,a)<-zip[-i..]x,a>0]!!1|(i,_)<-zip[0..]x]

Questo definisce una funzione chiamata f.

Spiegazione

Invece di iterare l'automa cellulare, calcolo direttamente i valori finali. La definizione è una comprensione di un singolo elenco. Il valore ivaria da 0a length x - 1, poiché comprimiamo xi numeri naturali. Per ogni indice i, produciamo l'elenco di elenchi a 2 elementi

[-(-i)^2, x0], [-(-i+1)^2, x1], [-(-i+2)^2, x2], ..., [-(-i+n)^2, xn]

Da questo elenco, calcoliamo l'elemento massimo la cui seconda coordinata è diversa da zero e prendiamo quel secondo elemento con !!1. Ciò fornisce il valore diverso da zero più vicino all'indice i, rompendo i legami prendendo il valore più grande.


Complimenti per aver vinto la taglia!
xnor

2

Lua, 133 byte

Due anelli, ternari nidificati ... Se voglio continuare a giocare a golf, dovrò trovare un altro modo per farlo, ma non ne vedo uno.

function f(a)for i=1,#a do b={}for j=1,#a do c,d=a[j+1]or 0,a[j-1]b[j]=0<a[j]and a[j]or(d or 0)>c and d or c end a=b end return a end

spiegazioni

function f(a)
  for i=1,#a                       -- this loop allow us to be sure the cycle is complete
  do
    b={}                           -- set a new pointer for b
    for j=1,#a                     -- loop used to iterate over all elements in a
    do
      c,d=a[j+1]or 0,a[j-1]        -- gains some bytes by attributing these expressions 
                                   -- to a variable
      b[j]=0<a[j]and a[j]or        -- explained below
            (d or 0)>c and d or c
    end
    a=b                            -- we are one cycle further, new value for a
  end                              -- which is our reference array
  return a
end

La parte

b[j]=0<a[j]and a[j]or(d or 0)>c and d or c 

sarà espanso a

b[j]=0<a[j]and a[j]or(a[j-1] or 0)>(a[j+1] or 0) and a[j-1] or(a[j+1]or 0) 

che può essere tradotto in nidificato ifcome

if 0<a[j]
then
    value=a[j]          -- if the cell isn't at 0, it keeps its value
elseif (a[j-1] or 0)<(a[j+1] or 0)
--[[ x or y as the following truth table :
x | y ||x or y
------||-------
0 | 0 || false
0 | 1 ||   y
1 | 0 ||   x
1 | 1 ||   x
    -- It means that when j=1 (1-based) and we try to index a[j-1]
    -- instead of failing, we will fall in the case false or true
    -- and use the value 0
    -- the same trick is used for when we try to use an index > a:len
]]--
then
    value=a[j-1]        -- the left cell propagate to the cell j
else
    value=a[j+1] or 0   -- if j=a:len, we put 0 instead of a[j+1]
                        -- this case can only be reached when we are on the right most cell
                        -- and a[j-1]==0
end

1

Pyth, 17 byte

meeSe#.e,_akdbQUQ

Prende un elenco in stile Python da stdin, output a stdout.

Spiegazione

Questa è fondamentalmente una traduzione della mia risposta Haskell. Non ho mai usato Pyth prima, quindi i suggerimenti sono i benvenuti.

                   Implicit: Q is input list
m              UQ  Map over input index d:
      .e      Q     Map over input index k and element b:
        ,_akdb       The pair [-abs(k-d), b]
    e#              Remove those where b==0
 eeS                Take the second element of the maximal pair

1

APL (Dyalog) , 18 byte

Funzione prefisso tacito anonimo.

(⊢+~∘××3⌈/0,,∘0)⍣≡

Provalo online!

(... )⍣≡ applica la seguente funzione tacita fino a quando il risultato non è identico all'argomento:

 l'argomento

+ più

  ~ non
   il
  × signum

× volte

3⌈/ i massimi su ciascun gruppo di tre di

0, zero seguito da

  , l'argomento seguito da
   uno
  0 zero


1

Java 8, 155 142 byte

a->{for(int b[],i,l=a.length,p,n,f=l;f>0;)for(b=a.clone(),i=0,f=l;i<l;f-=a[i-1]>0?1:0)if(a[i++]<1)a[i-1]=(p=i>1?b[i-2]:0)>(n=i<l?b[i]:0)?p:n;}

Modifica l'input int[] invece di restituirne uno nuovo per salvare i byte.

Spiegazione:

Provalo qui.

a->{                   // Method with integer-array parameter and no return-type
  for(int b[],         //  Copy array
          i,           //  Index integer
          l=a.length,  //  Length of the array
          p,n,         //  Temp integers (for previous and next)
          f=1;         //  Flag integer, starting at 1
      f>0;)            //  Loop (1) as long as the flag is not 0 (array contains zeroes)
    for(b=a.clone(),   //   Create a copy of the current state of the array
        i=0,           //   Reset the index to 0
        f=l;           //   Reset the flag to the length of the array `l`
        i<l;           //   Inner loop (2) over the array
        f-=a[i-1]>0?   //     After every iteration, if the current item is not a zero:
            1          //      Decrease flag `f` by 1
           :           //     Else:
            0)         //      Leave flag `f` the same
      if(a[i++]<1)     //    If the current item is a 0:
        a[i-1]=        //     Change the current item to:
         (p            //      If `p` (which is:
           =i>1?       //        If the current index is not 0:
             b[i-2]    //         `p` is the previous item
            :          //        Else:
             0)        //         `p` is 0)
         >(n           //      Is larger than `n` (which is:
            =i<l?      //        If the current index is not `l-1`:
              b[i]     //         `n` is the next item
             :         //        Else:
              0)?      //         `n` is 0):
          p            //       Set the current item to `p`
         :             //      Else:
          n;           //       Set the current item to `n`
                       //   End of inner loop (2) (implicit / single-line body)
                       //  End of loop (1) (implicit / single-line body)
}                      // End of method

0

Rubino, 81 byte

->(a){a.map{|o|a=a.map.with_index{|x,i|x!=0 ? x : a[[0,i-1].max..i+1].max}}[-1]}

Penso che l'interno mappotrebbe essere ulteriormente golfato.


Appena realizzato, la mia risposta è un po 'identica alla risposta di @ user81655 .
Harsh Gupta,

Penso che puoi rimuovere gli spazi nel ternario, cioè intorno ?e :.
Alex A.

0

PHP - 301 291 289 288 264 Characters

Non ho raggiunto il picco di altre risposte prima di provare questo. Non dare la colpa alla lingua, incolpami. Molto divertente e stimolante non meno. Tutti i consigli sul golf del codice sono molto apprezzati.

$a=explode(' ',$s);$f=1;while($s){$o=1;foreach($a as&$b){
if($b==0){$u=current($a);prev($a);$d=prev($a);if(!$o&&current($a)==0){end($a);$d=prev($a);}if(!$f){$f=1;continue;}if($u>$d)$b=$u;if($u<$d){$b=$d;$f=0;}}
$o=0;}if(!in_array(0,$a))break;}$r=join(' ',$a);echo$r;

spiegato

// Input
$s = '0 0 2 0 0 0 1 2 0 0 3 3 0 0';

// Create array
$a = explode(' ', $s);
// Set skip flag
$f = 1;
while ($s)
{
    // Set first flag
    $o = 1;
    // Foreach
    foreach ($a as &$b)
    {
        // Logic only for non zero numbers
        if ($b == 0)
        {
            // Get above and below value
            $u = current($a);
            prev($a);
            $d = prev($a);

            // Fix for last element
            if (! $o && current($a) == 0)
            {
                end($a);
                $d = prev($a);
            }

            // Skip flag to prevent upwards overrun
            if (! $f)
            {
                $f = 1;
                continue;
            }

            // Change zero value logic
            if ($u > $d)
                $b = $u;
            if ($u < $d)
            {
                $b = $d;
                $f = 0;
            }
        }

        // Turn off zero flag
        $o = 0;
    }

    // if array contains 0, start over, else end loop
    if (! in_array(0, $a))
        break;
}
// Return result
$r = join(' ', $a);
echo $r;(' ', $a);
echo $r;

1
Sul serio? Il golf non sta semplicemente rimuovendo gli spazi bianchi nel codice. Oltre all'algoritmo, ecco alcuni suggerimenti: usa 1piuttosto che true, splitpiuttosto che explode, forpiuttosto che while, joinpiuttosto che implode, rimuovere parentesi graffe inutili, ...
Blackhole

Ho continuato a esplodere perché la divisione è stata deprezzata. Inoltre, non so come scrivere un ciclo while usando for, quindi l'ho tenuto per ora, a meno che qualcuno qui non possa condividere le proprie conoscenze o condividere un collegamento. Grazie a tutti.
Oca,

0

Python, 71 byte

g=lambda l:l*all(l)or g([l[1]or max(l)for l in zip([0]+l,l,l[1:]+[0])])

Il zipcrea tutti i lunghezza-3 sottoliste di un elemento e dei suoi vicini, il trattamento al di là dei punti finali come 0. L'elemento centrale a l[1]un elenco secondario l, se zero, è sostituito da quello maxdei suoi vicini l[1]or max(l). I l*all(l)rendimenti della lista lquando non ha 0's.


0

Rubino, 74 byte

->a{(r=0...a.size).map{|n|a[r.min_by{|i|[(a[i]<1)?1:0,(i-n).abs,-a[i]]}]}}

funziona trovando il numero diverso da zero più vicino.


0

MATL , 38 byte

Traduzione diretta della mia risposta Matlab. Utilizza la versione corrente di language / compilatore.

it:"tttFFTo2X5I$X+wTFFo2X5I$X+vX>w~*+]

Esempio

>> matl it:"tttFFTo2X5I$X+wTFFo2X5I$X+vX>w~*+]
> [7 0 3 0 0 0 0 0 8 0 9 1]
7 7 3 3 3 8 8 8 8 9 9 1

EDIT: provalo online! con X+sostituito da Y+e vda &v, a causa di modifiche apportate nella lingua.

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.