任意のアイスキューブトレイの充填


27

このスペースとXのグリッドが、奇妙な形の空の角氷トレイの断面を表していると仮定します。

   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

のない列はX、水を保持できないトレイの穴または隙間を表し、無限の容量の流しに流れ込みます。グリッドの左端または右端から落ちる水も、この無限のシンクに流れ込みます。

蛇口をトレイの上に置き、すべてのコンパートメントの水位が安定するまで水で満たす場合、満たされる正確なコンパートメントは、水流がトレイの上に配置された正確な場所に依存します。(はねのない、薄くて安定した水の流れを想定してください。)


たとえば、蛇口Fが一番左のグリッド列の上にある場合

F                   
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

水はXその列の最上部に落ちて左右に広がり、左半分が下の流しにこぼれ、右半分が2×1コンパートメントを満たします。コンパートメントが満たされると、水流の右半分は流し台に流れ込むだけで、どこでも水位は本質的に安定しています。

蛇口をオフにすると、トレイは次のようになります:(~水として)

   X     X X        
X~~X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

同様に、蛇口を次のように配置すると:

   F                
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

左端の2つのコンパートメントがいっぱいになりますが、残りの水は排出されます。

   X     X X        
X~~X~X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

このように蛇口を配置すると:

         F          
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

ストリームの左半分は流し台に流れ込みますが、右半分は最終的に右端の3つのコンパートメントを満たします。これは、平らな面で水が水平方向に移動できる距離に制限がないためです。

   X     X~X        
X  X X  XX~X~~XX~~~X
XXXXXX XXXXXXXXXXXXX

ただし、次のように配置されます。

        F           
   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

すべての水が流れ出し、コンパートメントは満たされません。

   X     X X        
X  X X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX

チャレンジ

スペースX、およびの長方形のグリッドを取り込むプログラムまたは関数を記述しますF。一番上の行には常にが含まれ、Fそうでない場合はスペースのみが含まれます。X各列の」sは(もしあれば)グリッドの基部から実線アップに拡張する、すなわちない洞窟やオーバーハングが存在しないであろう。

上記のように、蛇口Fができることを水で満たした後、グリッドを印刷または返却し~ます。F出力の一番上の行を残します。

  • 蛇口列から離れたグリッドは最小で1×1になります。

    F
    X
    

    サポートする必要がある最小の入力です。

  • 入力は、完全なテキスト長方形として入力されます。入力および出力では、先頭と末尾のスペースが重要です。例えば、入力

        F     
      X  X    
      XXXX    
    

    結果になるはずです

      X~~X    
      XXXX    
    

    (先頭と末尾のスペースに注意してください)

  • 入力または出力に単一の末尾の改行があることは問題ありません。

  • あなたは、任意の4つの異なる使用することができ、印刷可能なASCII文字、スペースの代わりに文字をXF~

バイト単位の最短コードが優先されます。


大きな例:

入力:

                F                                 
              X             X                     
              X             X X                   
X            XXX       X    X X           X    X  
X   X     XXXXXXX      X    XXX     XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX

出力:

              X~~~~~~~~~~~~~X                     
              X~~~~~~~~~~~~~X~X                   
X~~~~~~~~~~~~XXX~~~~~~~X~~~~X~X~~~~~~~~~~~X    X  
X~~~X~~~~~XXXXXXX~~~~~~X~~~~XXX~~~~~XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX

そうそう、私の大好きなzip()<3 を使用する絶好の機会
cjfaure

2
これには答えが必要です:/私はそれに取り組みます。
TheNumberOne

これをシミュレートするセルオートマトンを作成するのは比較的簡単ですが、それを終了する方法は考えられません。
DanTheMan

まだ誰も競争していませんか?とてもかわいい挑戦。私は自分自身を打ち
負かさ

これの複製のように見えます:codegolf.stackexchange.com/questions/2563/fill-in-the-lakes
12Me21

回答:


1

perl -p0、204 + 2バイト

アイディア

  • Fの下の島の両側の高さが等しい場合、すべてのX *XesをX~*Xその島のesに置き換えます。
  • 片側が高い場合は、下側のドレインと下側の上部よりも高いFに最も近い点の間のすべてのX *XesをX~*Xesに置き換えます。

Fの真下の土地は、ここの両側の一部としてカウントされます。

ゴルフ

s/.*(F).*
//;$f=@-[1];($%,$r)=map{y///c}/(.{0,$f})\bX+?\b(.*)$/;($a,$b)=map{y///c}/[^~]*^(?(?=(.{$%,$f}X)).{$f} *|.{$f} *X(.*)).{$r}
/m;$a=$%if!$a||$b;$b+=$r;s/(?<=.{$a})\b *\b(?=.{$b})/"~"x length($&)/ge

ノート

perl -p0e ' # slurp stdin, print the result

s/.*(F).*\n//; # remove the first line, record the index of F
$f=@-[1]; # get the index of F

($l,$r)=map{length}m/(.{0,$f})\bX+?\b(.*)$/;
# gets the distance from either side to the drains closest to F
($a,$b)=map{length}m/[^~]*^(?(?=(.{$l,$f}X)).{$f} *|.{$f} *X(.*)).{$r}\n/m;
# tries to find the lowest line that has at least one X on
# one side of the island, but none on the other
$a=$l if !$a||$b;
$b+=$r; # use the captured groups to calculate the left and right bounds
s/(?<=.{$a})\b *\b(?=.{$b})/"~" x length($&)/ge;
# replace all pools within those bounds
'

Perlは可変長のルックビハインドをサポートしていないため、この実装の元のアルゴリズムを認識するのは難しいかもしれません。


6

Lua 5.2、581バイト

繰り返しになりますが、ゴルフのための非常に効果のない言語と効果のないアルゴリズムでスロースタート。しかし、私は改善します:)

r=io.read w=io.write F=r()f=F:find("F")o={[1]=F}W=#F i=2 
repeat s=r()if s==nil then break end o[i]={}for j=1,W do o[i][j]=s:sub(j,j)end i=i+1 until false
function e(i,j)
local k,l,b,c=j+1,j-1,false
if i>=#o or(o[i+1][j]==" "and e(i+1,j)==0)then return 0 end
while k<=W do
b=b or o[i][k]=="X"
if b or(o[i+1][k]==" "and e(i+1,k)==0)then break end
k=k+1 end
while l>0 do
c=c or o[i][l]=="X"
if c or(o[i+1][l]==" "and e(i+1,l)==0)then break end
l=l-1 end
if b and c then for m=l+1,k-1 do o[i][m]="~"end return 1 end
return 0 end
e(1,f)for i=2,#o do for j=1,W do w(o[i][j])end w"\n"end

テストケース(水源を使用):

---------
    F    
  X~~X   
  XXXX   
--------------------
         F          
   X     X~X        
X  X X  XX~X~~XX~~~X
XXXXXX XXXXXXXXXXXXX
--------------------
   F                
   X     X X        
X~~X~X  XX X  XX   X
XXXXXX XXXXXXXXXXXXX
--------------------------------------------------
                F                                 
              X~~~~~~~~~~~~~X                     
              X~~~~~~~~~~~~~X~X                   
X~~~~~~~~~~~~XXX~~~~~~~X~~~~X~X~~~~~~~~~~~X    X  
X~~~X~~~~~XXXXXXX~~~~~~X~~~~XXX~~~~~XXXXXXX X  X  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX

bashからこの方法でテストすることは可能ですが、見た目はあまり良くありません:

$ echo "    F     
  X  X    
  XXXX   " | lua f.lua

こちらのドキュメントを使用して、これを簡単にテストしてください!このように
-ravron

1

Javascript、460バイト

オンラインデモ(コンソールで、現在のChromeおよびFirefoxでテスト済み)。

function e(i,j){var k=j+1,l=j-1,b=0,c=0,I=i+1
if(i>(O-2)||(o[I][j]==" "&&e(I,j)==0))return 0
while(k<W){b=b||(o[i][k]=="X")
if(b||(o[I][k]==" "&&e(I,k)==0))break
k++}while(l>=0){c=c||(o[i][l]=="X")
if(c||(o[I][l]==" "&&e(I,l)==0))break
l--}if(b&&c){for(m=l+1;m<k;m++)o[i][m]="~"
return 1}return 0}function f(d){o=d.split("\n")
F=o[0];s=F.indexOf("F");W=F.length;O=o.length
for(i=0;i<O;i++)o[i]=o[i].split("")
e(0,s);for(i=1;i<O;i++)console.log(o[i].join(""))}

自分自身に挑戦することはそれほど楽しくありませんが、それでも可能です。Luaのものと同じアルゴリズムで、現在はJavaScriptになっています。

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