落ちてくる岩を予測する


18

この課題では、側面から見た2次元の地形の地図が与えられます。残念ながら、地形の一部は空中に浮いています。つまり、それらはcrash落します。あなたの仕事は、彼らが着陸する場所を予測することです。

入力

入力は、同じ長さの1つ以上の改行で区切られた文字列で、文字#(番号記号、岩を表す)または.(ピリオド、空の空間を表す)のみを含みます。

出力

出力の形式は入力と同じですが、次の変更が加えられています。入力文字列を岩の2次元グリッドとして表示します。隣接する岩の経路によってグリッドの下部に接続されている入力のすべての岩は硬いです。他の岩は緩いです。斜めに隣接する岩は隣接しているとは見なされません。すべての緩い岩は真っ直ぐに落ち、硬い岩または一番下の列の上のスタックになります。緩い岩は互いに付着していないため、大きな岩としてではなく、個々に落ちます。出力は、結果のグリッドです。

  • 入力

    ..###.
    .##.#.
    .#....
    .##.#.
    

    緩い岩が含まれていないため、出力は同じです。

  • 入力

    ...#..
    .#..#.
    .#..##
    .#...#
    .#####
    .#...#
    

    上部に緩い岩が1つあり、その下にある堅い岩の上に落ちます。出力は

    ......
    .#..#.
    .#..##
    .#.#.#
    .#####
    .#...#
    
  • 入力

    .#####....
    .#....####
    ###.###..#
    #.#...##..
    .####..#.#
    ......###.
    ..#...#..#
    ..#...#..#
    

    左側に緩い岩の大きなグループがあります。岩が落ちるとグループが壊れるので、出力は

    ..........
    ....######
    ..#.###..#
    . #...##..
    .##....#..
    .##...####
    ####..#..#
    #####.#..#
    

明確化

  • STDINから入力を取得してSTDOUTに出力するか、関数を記述できます。
  • これはコードゴルフなので、最短のプログラム(バイト単位)が勝者です。
  • 標準の抜け穴は許可されていません。

回答:


12

CJam、180 ... 133 101 ... 94 90 87バイト

qN/~'#/S*_,):L;]N*_,_,*{:A1$='#={[W1LL~)]Af+{W>},1$f=S&,{ASct}*}*}/N/z{S/{$W%}%'#*}%zN*

確かに多くのゴルフが可能ですが、完全に機能するようになった後に最初に投稿したかったのです。

見て!スクロールバーはありません!

(で構成岩グリッド取り.#STDINから末尾の改行せずに)およびSTDOUTに出力を印刷します

更新:硬い岩を把握するために、非効率的ではあるがより短い部分的な塗りつぶしを使用します。

更新2:岩を落とすためのアルゴリズムを変更しました。はるかに短くなりました!

更新3:いくつかの小さな最適化を行い、最終的にバイトカウントを元のコードの半分に減らすことができました!

仕組み

qN/~'#/S*_,):L;]N*             "Preparations";
qN/~                           "Read the input, split by new line and expand the array";
    '#/S*                      "In the last row, replace # by space";
         _,):L                 "Copy the last row and store length + 1 in L";
              ;]N*             "Pop the length, wrap everything in array and join by \n";

_,_,*{ ... }/                  "Flood fill";
_,                             "Copy the array and calculate its length";
  _,                           "Copy the length and calculate [0 - length] array";
    *                          "Repeat the above array, length times";
     { ... }/                  "Run the code block on each element of the array";

:A1$='#={ ... }*               "Process only #";
:A1$                           "Store the number in A and copy the input array to stack";
    =                          "Get Ath index element from input array";
     '#={ ... }*               "Run the code block if Ath element equals #";

[W1LL~)]Af+{W>},1$f=S&,{ASct}* "Flood fill spaces";
[W1LL~)]Af+                    "Get the indexes of the 4 elements on the cross formed by"
                               "the Ath index";
           {W>},               "Filter out the negative values";
                1$f=           "For each of the index, get the char from input string";
                    S&,        "Check if space is one of the 4 chars from above step";
                       {    }* "Run the code block if space is present";
                        ASct   "Make the Ath character of input string as space";

N/z{S/{$W%}%'#*}%zN*           "Let the rocks fall";
N/z                            "Split the resultant string by newlines and"
                               "transpose the matrix";
   {           }%              "Run the code block for each row (column of original)";
    S/{   }%                   "Split by space and run the code block for each part";
       $W%                     "Sort and reverse. This makes # come down and . to go up";
            '#*                "Join by 3, effectively replacing back spaces with #";
                 zN*           "Transpose to get back final matrix and join by newline";

フラッドフィルの場合、グリッドの長さ全体(グリッド)を繰り返し処理します。各反復で#、スペースに直接接している少なくとも1つを(スペース)に変換することが保証されています。ここのスペースは、堅固なロックグループを表しています。したがって、length(grid)の反復の終わりに、すべての硬い岩がスペースで表されることが保証されます。

こちらからオンラインでお試しください


15

Perl 5:98

2つのコマンドラインフラグを含む98。

#!perl -p0
1while/
/,($x="($`)")=~y!#!.!,s/#(.*
$)/%$1/+s/#$x?%|%$x?#/%$1$2%/s;1while s/#$x\./.$1#/s;y!%!#!

説明:

#!perl -p0 #read entire input to $_ and print at the end
/\n/;($x="($`)")=~y!#!.!; #calculate pattern matching space
                          #between two characters in the same column
                          #looks like "(......)" 
1 while s/#(.*\n$)/%$1/+s/#$x?%|%$x?#/%$1$2%/s;
                          #flood fill solid rock with %
1 while s/#$x\./.$1#/s;   #drop loose rock
y!%!#!                    #change % back to #

:@Optimizer私はきちんと仕上がっ参照された入力の最後の行に依存しているideone.com/7E3gQhそれが( -最終EOLの欠如反対に頼るか短い方)1つの文字の一匹狼となり、この依存せず。
nutki

1
CJamをほぼ30%倒しましたか?すごい。おめでとうございます。
DLosc 14

@DLoscもはやない:P
オプティマイザー

他の必須言語を100〜300%上回るでしょうか?すごい。おめでとうございます。;)
DLosc 14年

@DLosc上記の答えを見て、私はもはや命令型言語のリストにPerlを含めません:P
オプティマイザー

5

JavaScript(ES6)232

s=>{for(s=[...s+'1'.repeat(r=1+s.search('\n'))];s=s.map((c,p)=>c=='#'&(s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f;);for(;s.map((c,p)=>c=='#'&s[p+r]=='.'&&(s[p]='.',f=s[p+r]=c),f=0),f;);return s.join('').replace(/1/g,rok).slice(0,-r)}

文字列パラメーターを持ち、文字列を返す関数として。

最初に、最下行の「1」を追加して、接地線を識別します。
最初のループは、固定岩(「1」に近い)を検索し、それらを「1」としてマークします。検索は、硬い岩が見つからなくなるまで繰り返されます。
2番目のループは、残りの「#」文字を一番下の行に向かって移動します。繰り返しますが、これは岩が動かなくなるまで繰り返されます。
最後に、もう一度「1」を「#」に置き換えて、一番下の行を切り取ります。

少ないゴルフ

s=>{
  r = 1+s.search('\n');
  s = [...s+'1'.repeat(r)];
  for (; s = s.map((c,p) => c=='#' & (s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f; );
  for (; s.map((c,p) => c=='#' & s[p+r]=='.'&& (s[p] ='.', s[p+r]=c, f=1),f=0),f; );
  return s.join('')
    .replace(/1/g,'#')
    .slice(0,-r)
}

テスト (どの岩が硬く、何が落ちたかの証拠を得ることができます)

F=
s=>{for(s=[...s+'1'.repeat(r=1+s.search('\n'))];s=s.map((c,p)=>c=='#'&(s[p+1]|s[p-1]|s[p-r]|s[p+r])?f=1:c,f=0),f;);for(;s.map((c,p)=>c=='#'&s[p+r]=='.'&&(s[p]='.',f=s[p+r]=c),f=0),f;);return s.join('').replace(/1/g,rok).slice(0,-r)}

var rok // using rok that is 3 chars like '#'

function update() {
  rok = C.checked ? '@' : '#';
  O.textContent=F(I.textContent)
}

update()
td { padding: 5px }
pre { border: 1px solid #000; margin:0 }
<table><tr><td>Input</td><td>Output</td></tr>
<tr><td><pre id=I>.#####....
.#....####
###.###..#
#.#...##..
.####..#.#
......###.
..#...#..#
..#...#..#</pre></td>
<td><pre id=O></pre>
</td></tr></table>
<input type='checkbox' id=C oninput='update()'>Show firm rocks


3

APL、 130 119

'.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓ ⍉⊃⌈/(1,¨⍳⍴⊃↓x){x←⍵⋄(⍺⌷x)∧←2⋄x≡⍵:x⋄⊃⌈/((⊂⍴⍵)⌊¨1⌈(,∘-⍨↓∘.=⍨⍳2)+⊂⍺)∇¨⊂x}¨⊂⊖'#'=x←⎕]

(私の知る限り)入力が求められたときに改行を入力することはできないため、このプログラムは入力として文字行列を取ります。

使用されるアルゴリズムは、最初にバイナリ行列に変換されます(0空気で1岩)にから、下の行から塗りつぶして硬い岩をとしてマークし2ます。次に、各列を「硬い岩の間のスペース」に分割し、各パーティションを並べ替えて、ゆるい岩が「抜け落ちる」ようにします。

編集1:異なるフラッドフィルアルゴリズムを使用していくつかのゴルフ


テスト実行

実行1

文字行列Aを定義して印刷します。

      A←↑('.#####....') ('.#....####') ('###.###..#') ('#.#...##..') ('.####..#.#') ('......###.') ('..#...#..#') ('..#...#..#')
      A
.#####....
.#....####
###.###..#
#.#...##..
.####..#.#
......###.
..#...#..#
..#...#..#

次にA、プログラムにフィードします。

      '.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓⍉(1,¨⍳⊃⌽⍴x){⍵≡y←⊃⌈/x←⍺{x←⍵⋄(⍺⌷x)∧←2⋄x}¨⊂⍵:y⋄((⊂⍴⍵)⌊¨1⌈,(,∘-⍨↓∘.=⍨⍳2)∘.+⍺/⍨x≢¨⊂⍵)∇y}⊖'#'=x←⎕]
⎕:
      A
..........
....######
..#.###..#
..#...##..
.##....#..
.##...####
####..#..#
#####.#..#

実行2

      A←↑('#######')('#.....#')('#.#.#.#')('#.....#')('#######')
      A
#######
#.....#
#.#.#.#
#.....#
#######
      '.##'[1+⊖1↓⍉↑↑{,/{⍵[⍒⍵]}¨x⊂⍨2=x←2,⍵}¨↓⍉(1,¨⍳⊃⌽⍴x){⍵≡y←⊃⌈/x←⍺{x←⍵⋄(⍺⌷x)∧←2⋄x}¨⊂⍵:y⋄((⊂⍴⍵)⌊¨1⌈,(,∘-⍨↓∘.=⍨⍳2)∘.+⍺/⍨x≢¨⊂⍵)∇y}⊖'#'=x←⎕]
⎕:
      A
#######
#.....#
#.....#
#.#.#.#
#######

2

JS-443バイト

function g(b){function f(b,c,e){return b.substr(0,c)+e+b.substr(c+1)}function e(d,c){"#"==b[c][d]&&(b[c]=f(b[c],d,"F"),1<d&&e(d-1,c),d<w-1&&e(d+1,c),1<c&&e(d,c-1),c<h-1&&e(d,c+1))}b=b.split("\n");w=b[0].length;h=b.length;for(i=0;i<w;i++)"#"==b[h-1][i]&&e(i,h-1);for(j=h-2;-1<j;j--)for(i=0;i<w;i++)if(k=j+1,"#"==b[j][i]){for(;k<h&&"F"!=b[k][i]&&"#"!=b[k][i];)k++;k--;b[j]=f(b[j],i,".");b[k]=f(b[k],i,"#")}return b.join("\n").replace(/F/g,"#")};

洪水は、底から岩を満たし、次に、洪水のない岩を降ろします。フラッドフィルで多くの再帰を使用するため、ブラウザが少し遅れる場合があります。

それは関数です-で呼び出す g("input")

JSFiddle:http ://jsfiddle.net/mh66xge6/1/

Ungolfed JSFiddle:http ://jsfiddle.net/mh66xge6/


1

Python 3、364バイト

これからもっと絞り込めると思いますが、とにかくCJamやPerlと競合することは決してありません。

z="%";R=range
def F(r,c,g):
 if z>g[r][c]:g[r][c]=z;[F(r+d%2*(d-2),c+(d%2-1)*(d-1),g)for d in R(4)]
def P(s):
 t=s.split()[::-1];w=len(t[0]);g=[list(r+".")for r in t+["."*w]];[F(0,c,g)for c in R(w)]
 for c in R(w):
  for r in R(len(g)):
   while g[r][c]<z<g[r-1][c]and r:g[r][c],g[r-1][c]=".#";r-=1
 return"\n".join(''.join(r[:w])for r in g[-2::-1]).replace(z,"#")

他の回答と同様です。1つの癖は、最初にグリッドを上下逆にして(ループインデックスをより便利にするため)、余分な行と列を追加することです.-1インデックスのラッピングに関する問題を回避するため)。を呼び出して実行しP(string)ます。

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