細菌の増殖


25

標識された細菌のコロニー1を介して9空のセルと、等間隔のセルのセグメントで生をによって示さ0

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

毎秒、各コロニーは隣接する空のセルに広がります。2つのコロニーが同時に空のセルに到達すると、ラベルの大きいコロニーがそれを取得します。

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  

コロニーは境界を越えて広がることはできません。コロニーが別のコロニーに置き換えられることはないため、空のセルがすべて満たされると、それ以上変化することはありません。

初期状態を指定すると、最終状態を出力または印刷します。適切なリスト形式または文字列形式を使用します。中間状態は出力しないでください。入力には、少なくとも1つの細菌コロニーが含まれます。

関連: リスト内のゼロを隠します。(コロニーは右にのみ広がります。)

テストケース:入力以下の出力。

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

回答:


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。各セルと両側の2つのセルのすべてのリストを作成し、ゼロ化された各セルを隣接セルの最大値に更新することにより、更新を適用します。

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人の隣人が必要なので、1
  • nは通常、色の数またはリスト(異なるセルタイプ)ですが、ルールをルール番号ではなくカスタム関数として指定する場合、これはである必要があります{}
  • f更新ルールを決定する関数です。3つのセル(ifの場合r = 1)のリストを取り、中央のセルの新しい色を返します。
  • iは初期条件です。それが入力です。
  • b背景です。これが指定されていない場合、CellularAutomaton周期的な境界を使用しますが、これは望ましくありません。代わりに使用0すると、デッド境界条件が課されます。
  • tシミュレートする回数です。その後、バクテリアが収束するので、入力が広い以上のステップは必要ありませんt = Length@#。通常、CellularAutomatonすべての中間ステップを返します。これを避けるにはt、2つのリストにラップします。
  • 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の場合、隣接要素の最大値を取得します。入力の長さを繰り返します。このため、x経由で繰り返しfoldlますが、の2番目の引数は無視しpます。

編集:@Maurisは保存するために6バイトを見つけ、@ xnorはさらに2バイト見つけました。ありがとう!


置換h pしてp!_から置換(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.
  }%
}*

収束を回避することは素晴らしいトリックです
ルイスメンドー

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。以前のリリースでは、次のように1バイト余分に必要です。

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のソリューションと、リストの変更が停止したかどうかをテストする必要がないことを理解するのに役立つ説明感謝します。すべてのゼロがカバーされていることを確認するのに十分な回数だけ繰り返す必要があります。(必要な反復の最大数は、リストの長さよりも1つ少なくなります。これにより、コードの使用量が少なくなるため、それ以上の反復が行われます。)


@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範囲はからです。各インデックスに対して、2要素リストのリストを作成します0length x - 1xi

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

このリストから、2番目の座標がゼロ以外の最大要素を計算し、その2番目の要素をで取得し!!1ます。これにより、indexに最も近い非ゼロ値が与えiられ、より大きな値を取ることで関係が破壊されます。


賞金を獲得しておめでとうございます!
XNOR

2

Lua、133バイト

2つのループ、ネストされた3つの要素...さらにゴルフをしたい場合、別の方法を見つける必要がありますが、1つは表示されません。

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

Pythonスタイルのリストを標準入力から取得し、標準出力に出力します。

説明

これは基本的に私の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⌈/ 3つの各グループの最大値

0, ゼロの後に

  , 引数が続く ゼロ
  
  0


1

ジャワ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、役に立たない中括弧を削除するには、...
ブラックホール

分割が減価償却されているため、爆発し続けました。また、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サブリストを作成します0。中央要素l[1]のサブリストl(ゼロの場合)はmax、その近傍ので置き換えられl[1]or max(l)ます。l*all(l)リターンリストlそれは持っていない0のを。


0

ルビー、74バイト

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

最も近い非ゼロの数を見つけることによって機能します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.