Expansão bacteriana

25

As colónias de bactérias marcadas 1através 9vivo em um segmento de células igualmente espaçados, com células vazias indicado pela0

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

A cada segundo, cada colônia se espalha para células vazias adjacentes. Se duas colônias alcançam uma célula vazia ao mesmo tempo, a colônia com etiqueta maior a pega.

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  

As colônias não podem se espalhar além dos limites. Uma colônia nunca é deslocada por outra colônia; portanto, quando todas as células vazias são preenchidas, nada mais muda.

Dado o estado inicial, produza ou imprima o estado final. Use qualquer lista razoável ou formato de sequência. Você não deve emitir nenhum estado intermediário. A entrada conterá pelo menos uma colônia bacteriana.

Relacionado: Encobrir zeros em uma lista . (As colônias se espalham apenas para a direita.)

Casos de teste: Saída abaixo da entrada.

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

xnor
fonte

Respostas:

14

JavaScript (ES6), 66 62 bytes

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

Explicação

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

Teste

user81655
fonte
10

Pitão, 18 bytes

um|@d1eSd.:++0G03Q

Suíte de teste

Recebe a entrada como uma lista de números inteiros.

Essencialmente, isso usa um loop aplicar até convergência u,. Aplica a atualização formando todas as listas de cada célula e as duas células de cada lado e atualizando cada célula zerada ao máximo de seus vizinhos.

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.
isaacg
fonte
8

Mathematica, 77 bytes

Não é muito competitivo em comparação com a //.solução de alefalpha , mas imaginei que um desafio de deveria ter uma CellularAutomatonresposta:

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

A função usa muitos parâmetros ... vamos dar alguns nomes a eles:

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

Aqui está o que eles fazem:

  • ré o intervalo da regra, ou seja, determina quantos vizinhos são considerados para a atualização. Queremos um vizinho de cada lado, então usamos 1.
  • nnormalmente é o número ou a lista de cores (diferentes tipos de células), mas se especificarmos a regra como uma função personalizada em vez de um número de regra, deve ser {}.
  • fé uma função que determina a regra de atualização. Ele pega uma lista de 3 células (se r = 1) e retorna a nova cor para a célula do meio.
  • ié a condição inicial. Essa é a entrada.
  • bé o plano de fundo. Se isso não for dado, CellularAutomatonusa limites periódicos, o que não queremos. Em vez disso, o uso 0impõe uma condição de limite morto.
  • té o número de vezes para simular. Não precisamos de mais etapas do que a entrada é ampla, porque depois disso as bactérias convergiram t = Length@#. Normalmente, CellularAutomatonretorna todas as etapas intermediárias. Podemos evitar isso envolto tem duas listas.
  • ddetermina quais células são apresentadas na saída. Por padrão, obteríamos todas as células que poderiam ser afetadas pela regra (que são t*rcélulas adicionais em cada extremidade da entrada). Damos l-1, porque essa é uma das poucas situações no Mathematica em que um índice baseado em zero é usado.
Martin Ender
fonte
6

Haskell, 86 83 81 79 73 71 bytes

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

Exemplo de uso: 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].

Não há muito a explicar: se uma célula for 0, use o máximo dos elementos vizinhos. Repita os tempos de duração da entrada. Para isso, repito xvia, foldlmas ignoro o segundo argumento em p.

Edit: @Mauris encontrou 6 bytes para salvar e @xnor outros dois. Obrigado!

nimi
fonte
Você pode substituir h ppor p!_e substituir (const.h)por (!)para salvar 6 bytes.
21415 Lynn
@Mauris: Inteligente. Muito obrigado!
nimi
@ nimi Acho que a última linha anonimamente id>>=foldl(!).
Xnor
@ xnor: sim, sim! Bem manchado!
nimi
4

CJam, 27 24 bytes

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

Teste aqui.

Isso empurra um bloco sem nome que transforma uma lista na pilha em uma nova lista.

Explicação

_,       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.
  }%
}*
Martin Ender
fonte
Evitar a convergência é um bom truque #
Luis Mendo
1
... o que eu descaradamente emprestado :-)
Luis Mendo
4

J, 24 23 bytes

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

Uso:

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

O método é semelhante à solução de 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

Experimente online aqui.

1 byte economizado graças ao Zgarb.

randomra
fonte
3

Mathematica, 77 74 66 62 bytes

Economizou 12 bytes graças a Martin Büttner.

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

J, 33 bytes

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

Um pouco mais do que eu gostaria.

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.
Lynn
fonte
Isso é tão diferente do que eu tenho, eu acho que você deve publicá-la como uma resposta :)
Lynn
3

Python 3.5, 83 bytes

Esta função pega uma lista Python de números inteiros. Não tenho certeza se ainda há muito para jogar golfe, mas eu adoraria competir com outro idioma, pelo menos!

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

De Python 3.5, PEP 448 nos permite descompactar sem 0,*s. As versões anteriores exigem um byte extra, da seguinte forma:

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

Os nossos agradecimentos à solução e explicação do user81655 por me ajudarem a perceber que não preciso testar se a lista parou de mudar; Eu só preciso iterar vezes suficientes para garantir que todos os zeros tenham sido cobertos. (O número máximo de iterações necessárias é um menor que o comprimento da lista; isso faz uma iteração mais que isso, porque isso requer menos código.)

Tim Pederick
fonte
@ Chrish: Ele não funciona no Python 3.5 e também não acho que funcionaria em versões anteriores: isso não move o returnpara dentro do for _ in sloop?
Tim Pederick
comentário excluído - por acaso tentei apenas os casos de teste que são resolvidos pela primeira vez.
Chris H
3

Matlab, 90 bytes

Que tal algumas convoluções?

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

Exemplo

>> 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
Luis Mendo
fonte
3

Haskell, 66 65 bytes

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

Isso define uma função chamada f.

Explicação

Em vez de iterar o autômato celular, eu computo os valores finais diretamente. A definição é uma compreensão de lista única. O valor ivaria de 0a length x - 1, pois zipamos xcom os números naturais. Para cada índice i, produzimos a lista de listas de 2 elementos

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

Nesta lista, calculamos o elemento máximo cuja segunda coordenada é diferente de zero e levamos esse segundo elemento !!1. Isso fornece o valor diferente de zero mais próximo do índice i, rompendo os laços ao obter o valor maior.

Zgarb
fonte
Parabéns por ganhar a recompensa!
xnor
2

Lua, 133 bytes

Dois loops, ternários aninhados ... Se eu quiser jogar mais, vou ter que encontrar uma outra maneira de fazer isso, mas não vejo um.

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

Explicações

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

A parte

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

será expandido para

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) 

que pode ser traduzido em aninhado ifcomo

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
Katenkyo
fonte
1

Pitão, 17 bytes

meeSe#.e,_akdbQUQ

Pega uma lista no estilo Python de stdin, sai para stdout.

Explicação

Esta é basicamente uma tradução da minha resposta Haskell. Eu realmente não usei Pyth antes, então dicas são bem-vindas.

                   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
Zgarb
fonte
1

APL (Dyalog) , 18 bytes

Função de prefixo tácito anônimo.

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

Experimente online!

()⍣≡ Aplique a seguinte função tácita até que o resultado seja idêntico ao argumento:

 o argumento

+ mais

  ~ não
   o
  × signum

× vezes

3⌈/ os máximos sobre cada grupo de três de

0, zero seguido por

  , o argumento seguido por
   um
  0 zero

Adão
fonte
1

Java 8, 155 142 bytes

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 a entrada em int[]vez de retornar uma nova para salvar bytes.

Explicação:

Experimente aqui.

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
Kevin Cruijssen
fonte
0

Ruby, 81 bytes

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

Eu acho que o interior mappoderia ser ainda mais jogado.

Harsh Gupta
fonte
Acabo de perceber, minha resposta é meio idêntica à resposta do @ user81655 .
Harsh Gupta
Eu acho que você pode remover os espaços no ternário, ou seja, ao redor ?e :.
Alex A.
0

PHP - 301 291 289 288 264 caracteres

Não deu pico em outras respostas antes de tentar isso. Não culpe a língua, culpe-me. Muito agradável e desafiador, não obstante. Todos os conselhos sobre códigos de golfe são muito apreciados.

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

Explicado

// 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;
Ganso
fonte
1
A sério? Golfe não é apenas remover os espaços em branco no seu código. Além do algoritmo, aqui estão algumas dicas: uso 1ao invés de true, splitem vez de explode, forao invés de while, joinem vez de implode, remover chaves inúteis, ...
Blackhole
Eu continuei explodindo porque a divisão está sendo depreciada. Além disso, não sei como escrever um loop while usando for, então guardei-o por enquanto, a menos que alguém aqui possa compartilhar seu conhecimento ou compartilhar um link. Obrigado a todos.
Goose
0

Python, 71 bytes

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

A zipcria todos Comprimento-3 sublists de um elemento e os seus vizinhos, o tratamento para além dos pontos de extremidade como 0. O elemento central no qual l[1]uma sublist l, se zero, é substituída pelo maxde seus vizinhos por l[1]or max(l). As l*all(l)retorna a lista lquando ele não tem 0's.

xnor
fonte
0

Ruby, 74 bytes

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

funciona encontrando o número diferente de zero mais próximo.

MegaTom
fonte
0

MATL , 38 bytes

Tradução direta da minha resposta do Matlab. Usa a versão atual do idioma / compilador.

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

Exemplo

>> 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: Experimente online! com X+substituído por Y+e vpor &v, devido a mudanças feitas no idioma.

Luis Mendo
fonte