细菌膨胀


25

1通过活菌标记的细菌菌落9生活在一段等距的细胞中,空细胞表示为0

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

每隔一秒钟,每个菌落就会扩散到相邻的空细胞中。如果两个菌落同时到达一个空细胞,则标记较大的菌落将其带走。

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  

殖民地不能扩散到边界之外。一个殖民地永远不会被另一个殖民地所取代,因此一旦所有空单元都被填满,就不会有任何进一步的变化。

给定初始状态,输出或打印最终状态。使用任何合理的列表或字符串格式。您不应输出任何中间状态。输入将包含至少一个细菌菌落。

相关: 掩盖列表中的零。(殖民地只向右扩散。)

测试用例:输出低于输入。

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

Answers:


14

JavaScript(ES6),66 62字节

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

说明

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

测试


10

Pyth,18个字节

um|@d1eSd.:++0G03Q

测试套件

将输入作为整数列表。

本质上,这使用了应用直到收敛循环u。它通过形成每个像元以及任一侧的两个像元的所有列表,然后将每个清零的像元更新为其邻居的最大值来应用更新。

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个字节

与alephalpha的//.解决方案相比,竞争并不十分激烈,但我认为 应对挑战应该有一个CellularAutomaton答案:

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

该函数需要大量参数...让我们给它们起一些名字:

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

这是他们的工作:

  • r是规则的范围,即确定要考虑的邻居数量。我们希望每边都有一个邻居,所以我们使用1
  • n通常是颜色的数量或列表(不同的单元格类型),但是如果我们将规则指定为自定义函数而不是规则编号,则应为{}
  • f是确定更新规则的功能。它接受3个单元格的列表(如果r = 1),并为中间单元格返回新颜色。
  • i是初始条件。这就是输入。
  • b是背景。如果没有给出,则CellularAutomaton使用我们不希望的周期性边界。相反,使用会0施加死边界条件。
  • t是模拟的次数。我们不需要超出输入范围的更多步骤,因为在那之后细菌将汇聚,因此t = Length@#。通常,CellularAutomaton返回所有中间步骤。我们可以通过包装t在两个列表中来避免这种情况。
  • d确定在输出中显示哪些单元格。默认情况下,我们将获取所有可能受到该规则影响的t*r单元格(输入两端的其他单元格)。我们给出它l-1,因为这是在Mathematica中使用基于零的索引的少数情况之一。

6

Haskell,86 83 81 79 73 71字节

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

用法示例: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]

没什么可解释的:如果单元格为0,则取最大的相邻元素。重复输入时间的长度。为此,我遍历了xvia,foldl但忽略了中的第二个参数p

编辑:@Mauris发现有6个字节要保存,@ xnor发现另外两个字节。谢谢!


您可以替换为h pp!_然后替换(const.h)(!)以保存6个字节。
林恩

@毛里斯:聪明。非常感谢!
NIMI

@nimi我认为最后一行匿名化为id>>=foldl(!)
xnor

@xnor:是的!好眼力!
nimi

4

CJam,27个 24字节

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

在这里测试。

这将推送一个未命名的块,该块将堆栈上的列表转换为新列表。

说明

_,       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.
  }%
}*

避开收敛是一个不错的技巧
Luis Mendo 2015年

1
...我无耻地借用了:-)
路易斯·门多

4

J,24 23字节

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

用法:

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

方法类似于毛里斯的解

(                  )^:_ 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

在这里在线尝试。

感谢Zgarb,节省了1个字节。


3

Mathematica,77 74 66 62字节

感谢MartinBüttner,节省了12个字节。

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

3

J,33个字节

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

比我想要的要长一点。

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

3

Python 3.5,83个字节

此函数采用Python整数列表。不确定还有很多事情要做,但是我希望至少能和其他语言保持竞争力!

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

从Python 3.5开始,PEP 448使我们可以解压s0,*s。较早的版本需要额外增加一个字节,如下所示:

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

感谢user81655的解决方案,并解释帮助我意识到,名单是否已经停止改变我不需要测试; 我只需要迭代足够的时间以确保必须覆盖所有零。(所需的最大迭代次数比列表的长度少一;这比列表的长度少一倍,因为这需要更少的代码。)


@ChrisH:这是行不通的关于Python 3.5的,我不认为它会在较早版本的工作之一:不认为移动return内部for _ in s循环?
蒂姆·佩德瑞克

注释已删除-我碰巧只尝试了第一次解决的测试用例。
克里斯H

3

Matlab,90个字节

一些卷积怎么样?

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

>> 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字节

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

这定义了一个称为 f

说明

我没有迭代元胞自动机,而是直接计算最终值。该定义是单个列表理解。值i范围从0length x - 1,因为我们x使用自然数压缩。对于每个索引i,我们生成2元素列表的列表

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

从此列表中,我们计算第二个坐标非零的最大元素,并使用来获取第二个元素!!1。这将为index提供最接近的非零值i,并通过取更大的值来打破平局。


恭喜获得赏金!
xnor 2015年

2

Lua,133个字节

两个循环,嵌套的三元组...如果我想进一步打高尔夫球,我将不得不寻找另一种方法,但是我看不到。

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

说明

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

那个部分

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

将扩展到

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) 

可以在嵌套被翻译if

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个字节

meeSe#.e,_akdbQUQ

从stdin获取Python样式的列表,输出到stdout。

说明

这基本上是我的Haskell答案的翻译。我以前还没有真正使用过Pyth,因此欢迎您提供提示。

                   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字节

匿名默认前缀功能。

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

在线尝试!

()⍣≡ 应用以下默认函数,直到结果与参数相同:

 论点

+ 加

  ~ 不是
   的
  × 正负号

× 次

3⌈/ 每组三个中的最大值

0, 零后跟

  , 参数后跟
   一个
  0 零


1

Java的8,155个 142字节

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

修改输入,int[]而不是返回新的输入以节省字节。

说明:

在这里尝试。

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

PHP - 301个 291 289 288 264字符

尝试之前没有在其他答案上达到顶峰。不要怪语言,怪我。非常令人愉快和具有挑战性的。所有代码高尔夫建议深表赞赏。

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

讲解

// 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
认真吗 打高尔夫不仅仅是删除代码中的空格。除了算法外,这里还有一些技巧:使用1而不是truesplit而不是explodefor而不是whilejoin而不是implode,删除无用的花括号,…
Blackhole 2015年

我一直在爆炸,因为split正在贬值。另外,我不知道如何使用for编写while循环,所以我暂时保留了它,除非这里的人可以分享他们的知识或分享链接。谢谢你们。

0

Python,71个字节

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

所述zip创建了一个元素和它的邻居的所有长度为3的子列表,治疗超出端点作为0l[1]子列表的中心元素l(如果为零)将替换max为其邻居的l[1]or max(l)。如果没有,则l*all(l)返回列表。l0


0

Ruby,74个字节

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

通过查找最接近的非零数字来工作。


0

玛特,38字节

我的Matlab答案的直接翻译。使用当前版本的语言/编译器。

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

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

编辑:在线尝试!X+替换Y+v通过&v,由于在语言所作的更改。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.