政府は壁の供給が制限されています


28

前書き

知識のあるコードゴルファーは、終末の洪水に備えてくれました。危険にさらされている地域は避難し、人口は高地に移動しました。

洪水を過小評価していました(または、@ user12345のコードにバグがあった可能性があります)。いくつかの高地地域は、海面に急速に近づいています。人口密度の高い野営地の生存を確保するために、壁を建てる必要があります。悲しいことに、政府は壁の供給が限られています。

問題

終末シナリオは、1行に2つの数字で記述されnていmます。その行に続くのは、1行ごとの値nm持つ行で、単一のスペースで区切られています。各値は4文字のうちの1つです。

  • x通れません。ここには水が流れません。ここに壁を建てることはできません。
  • -不安定。ここを水が流れることができます。ここに壁を建てることはできません。
  • .安定。ここを水が流れることができます。ここに壁を建てることができます。
  • o野営地。ここを水が流れることができます。もしそうなら、誰もが死ぬ。ここに壁を建てることはできません。

エッジが通過できないか、タイルに壁が構築されていない限り、水はマップのすべてのエッジから流れます。野営地を保護するために必要な最小数の壁を出力できるプログラムを作成します。

入力例

 6 7
 x . . x x x x
 x . . x - - x
 x . x x - - x
 x . o o o - .
 x . o o o - .
 x x x x x x x

出力例

3

仮定

  • 水は直角にのみ流れる
  • 野営地は、シナリオごとに1つの直交する連続したブロックとしてのみ存在します
  • ソリューションは常に存在します(ただし、大量の壁が必要になる場合があります)
  • シナリオには解決策がないため、野営地を端に配置することはできません
  • 2 << n16
  • 2 << m16
  • 入力は、stdinから提供されるか、「city.txt」から読み取られるか、単一の引数として受け入れられます

最短のコードが勝ちます!


2
プログラムが正しくても、問題の特定のインスタンスの解決策を提供するために既知の宇宙が存在していたよりも時間がかかりますか?
Claudiu 14年

@Claudiu私はCode Golfにいくらか慣れています。私の要件は時間制限の指定に失敗したため、時間制限は存在しません。解決策が問題のすべてのインスタンスに対して正しいことを証明するために、負担は答えに落ちます。賢明/クールな方法でいくつかの(すべてではない)インスタンスを解決するソリューションがある場合、楽しみのために投稿することをお勧めします。
レインボルト14年

2
コードゴルフは通常、時間制限を必要としません。
Hosch250 14年

クール!別のQ:入力は指定どおりにする必要がありますか、それとも別の形式で入力できますか?
Claudiu 14年

@Claudiu要件以外のものは受け入れられません。ただし、編集ボタンを使用して要件の編集を提案できます。まだ答えがないので、すぐに編集を受け入れます。
レインボルト14年

回答:


10

Mathematicaの、257の 253文字

d="city.txt"~Import~"Table";g=EdgeAdd[#,∞<->Tr@#&/@Position[VertexDegree@#,2|3]]&@GridGraph@d[[1,{2,1}]];{o,x,s}=Tr/@Position[Join@@d[[2;;]],#]&/@{"o","x","."};Catch@Do[If[Min[GraphDistance[VertexDelete[g,x⋃w],∞,#]&/@o]==∞,Throw@Length@w],{w,Subsets@s}]

入力はから読み取られ"city.txt"ます。

説明:

Mathematicaにはグラフを扱う多くの関数があります。

最初に、からデータを読み取ります"city.txt"

d="city.txt"~Import~"Table";

次に、 'm' * 'n'頂点()を使用してグリッドグラフを作成し、それにグラフGridGraph@d[[1,{2,1}]]の「エッジ」のすべての頂点に接続される「無限遠の頂点」を追加します。この頂点は水が流れる場所です。

g=EdgeAdd[#,∞<->Tr@#&/@Position[VertexDegree@#,2|3]]&@GridGraph@d[[1,{2,1}]];

およびoxおよびsは、「o」、「x」、および「。」の位置を示します。それぞれ。

{o,x,s}=Tr/@Position[Join@@d[[2;;]],#]&/@{"o","x","."};

次にws(サブセットは長さでソートされます)の任意のサブセットについて、()内xおよび()wから頂点を削除し、「無限大の頂点」から野営地までの最短経路の長さを見つけます。長さが無限であれば、野営地は安全です。したがって、最初のものの長さは、野営地を保護するために必要な壁の最小数です。gVertexDelete[g,x⋃w]ow

Catch@Do[If[Min[GraphDistance[VertexDelete[g,x⋃w],∞,#]&/@o]==∞,Throw@Length@w],{w,Subsets@s}]

いいね!私は、異なる言語の異なるアプローチにscられるだろうと考えました。
Claudiu 14年

1
賛成ですが、あなたが私たちの残りのためにあなたのコードを説明するならば、私はもっと誇らしげにそうします。
マイケルスターン14年

誰かがこの答えが正しいことを保証したり、「Mathematica」のオンライン通訳を提供したりできますか?見つけられない。
レインボルト

1
@Rusher私はそれを検証しました、そしてそれはしっかりしています。MM用のオンラインインタープリターはありませんが、ダウンロード可能なCDFドキュメント形式があり、私と他のカップルがソリューションを共有するための実験を開始しました。Raspberry Pi ARMコンピューターを使用してMathematicaを無料で入手することもできますが、ボックスの計算能力によって制限されていることに注意してください。FWIW、私たちMMユーザーが正直なお互いを維持するために最善を尽くし、我々は(また、Matlabの、メープル、モノの仕事をしませんMS言語などが直面する問題は)私たちの提出をよりアクセス作ることに取り組んでいる
ジョナサン・バンをマトレ

4

C、827 799 522

ゴルフ:

#define N for(
#define F(W,X,Y,Z) N i= W;i X Y;i Z)
#define C(A,B,C) if(c[A][B]==C)
#define S(W,X,Y,Z,A,B) p=1;F(W,X,Y,Z)C(A,B,120)p=0;if(p){F(W,X,Y,Z){C(A,B,46){c[A][B]='x';z++;Q();break;}}}else{F(W,X,Y,Z){C(A,B,120)break;else c[A][B]='o';}}
p,m,z,w,h,o,i,u,l,x,y;char c[16][16];Q(){N u=0;u<h;u++)N l=0;l<w;l++)if(c[u][l]=='o'){x=u;y=l;S(x,>,m,--,i,y)S(y,>,m,--,x,i)S(y,<,w,++,x,i)S(x,<,h,++,i,y)}}main(int a, char **v){h=atoi(v[1]);w=atoi(v[2]);N m=-1;o<h;o++)N i=0;i<w;i++)scanf("%c",&c[o][i]);Q();printf("%d",z);}

入力は高さとコマンドライン引数として与えられ、グリッドは次のように標準./a.out 6 7 < input入力で単一の文字列として読み込まれます:入力はこの形式(左から右、上から下)にあります:

x..xxxxx..x--xx.xx--xx.ooo-.x.ooo-.xxxxxxx

「読み取り可能」:

#define F(W,X,Y,Z) for(i= W;i X Y;i Z)
#define C(A,B,C) if(c[A][B]==C)
#define S(W,X,Y,Z,A,B) p=1;F(W,X,Y,Z)C(A,B,120)p=0;if(p){F(W,X,Y,Z){C(A,B,46){c[A][B]='x';z++;Q();break;}}}else{F(W,X,Y,Z){C(A,B,120)break;else c[A][B]='o';}}

/*Example of an expanded "S" macro:
p=1;
for(i=x;i>m;i--) if(c[i][y]==120) p=0;
if(p)
{
    for(i=x;i>m;i--)
    {
        if(c[i][y]==46)
        {
            c[i][y]='x';
            z++;
            Q();
            break;
        }
    }
}
else
{
    for(i= x;i > m;i --)
    {
        if(c[i][y]==120) break;
        else c[i][y]='o';
    }
}
*/

p,m,z,w,h,o,i,u,l,x,y;
char c[16][16];
Q(){
    for(u=0;u<h;u++)
        for(l=0;l<w;l++)
            if(c[u][l]=='o')
            {
        x=u;y=l;
        S(x,>,m,--,i,y)
        S(y,>,m,--,x,i)
        S(y,<,w,++,x,i)
        S(x,<,h,++,i,y)
            }
}

main(int a, char **v)
{
    h=atoi(v[1]);
    w=atoi(v[2]);
    for(m=-1;o<h;o++)
        for(i=0;i<w;i++)
            scanf("%c",&c[o][i]);
    P();
    Q();
    printf("%d\n",z);
    P();
}

//Omitted in golfed version, prints the map.
P()
{
    for(o=0;o<h;o++)
    {
        for (i=0;i<w;i++) printf("%c",c[o][i]);
        printf("\n");
    }   
}

@Claudiuによるソリューションほど短いものではありませんが、非常に高速に実行されます。端からあふれるのではなく、野営地を見つけ、「o」トークンから外側に向かって働きます。

  • 野営地の隣の不安定な地面に遭遇すると、野営地をその上に拡大します。
  • グリッド上の陣営に各方向に少なくとも1つの壁がない場合、壁を構築できるまでその方向に移動します。
  • 新しい壁セクションが配置されるたびに、次の壁セクションを見つけるために再帰します。

サンプル壁の配置:

x..xxxx                           x..xxxx
x..x--x                           x..xoox
x.xx--x                           x3xxoox
x.ooo-.  <-- results in this -->  xooooo1
x.ooo-.                           xooooo2
xxxxxxx                           xxxxxxx

面白いアプローチ!常に最短の回答が得られますか?たとえば、このマップに対してどのような答えが得られますか?それは3でなければなりません(新しい壁がどこに行くのかを示す@)。自分でコードを実行しようとしましたが、動作していないようです
Claudiu 14年

おっと、ゴルフとアルコールがあまりうまく混ざっていないようです...私はいくつかの未定義の行動でゴルフをしました。277個の不要な文字とともに修正する必要があります。
コミンテルン14年

2
@Claudiu -上記の私のコメントを参照してください、あなたが投稿マップの結果がでているpastebin.com/r9fv7tC5。これにより、常に最短の回答が得られるはずですが、私は、コーナーケースを提示する可能性があると考えた10または15のマップでのみテストしました。失敗したマップを特定できる人がいるかどうかを知りたいです。
コミンテルン14年

4

Python、553 525 512 449 414 404 387 368文字(呼び出しで+4?)

これをゴルフするのはとても楽しかった。圧縮しようとすると、82バイト大きくなります!今、それはコンパクトさと繰り返しの欠如の尺度です。

R=range;import itertools as I
f=map(str.split,open('city.txt'))[1:]
S=[]
def D(q):
 q=set(q)
 def C(*a):
    r,c=a
    try:p=(f[r][c],'x')[a in q]
    except:p='x'
    q.add(a)
    if'.'==p:S[:0]=[a]
    return p<'/'and C(r+1,c)|C(r-1,c)|C(r,c+1)|C(r,c-1)or'o'==p
 if sum(C(j,0)|C(j,-1)|C(0,j)|C(-1,j)for j in R(16))<1:print n;B
D(S);Z=S[:]
for n in R(len(Z)):map(D,I.combinations(Z,n))

インデントレベルはスペース、タブです。

使用法

からの読み取りcity.txt

6 7
x . . x x x x
x . . x - - x
x . x x - - x
x . o o o - .
x . o o o - .
x x x x x x x

次のように呼び出します。

$ python floodfill_golf.py 2>X
3

2>X例外を発生させることにより、プログラムの終了以来、標準エラー出力を非表示にすることです。これが不公平と見なされる場合は、呼び出しに4文字を追加してください。

説明

単純な総当たり。C塗りつぶしを行い、野営地に到達した場合にtrueを返します。パディングを適切に設定するためにスペースを取りすぎたため、余分なパディングはありません。D、埋める壁のセットが与えられるCと、エッジのすべてのポイントからCそれらの壁を説明するように呼び出し、長さが印刷され、陣営に達していない場合は終了します。壁のリストは、塗りつぶしの追跡にも使用されるため、ボードのコピーは必要ありません!厄介なことに、C見つかった空のスポットもリストに追加しますS。したがって、この関数Dは最初に空のスポットのリストを作成するために使用されます。このため、最初の実行時にすべてのが収集されるようsumany、ではなくを使用.します。

D一度呼び出してZから、空のスポットのリストをコピーします。これは、S追加され続けるためです(非効率ですが、文字数が少なくなります)。次にitertools.combinations、0スポットから空のスポットの各コンボを選択するために使用します。各コンボを実行しますDと、動作する最初のの長さが出力され、プログラムを終了する例外が発生します。答えが見つからない場合、何も印刷されません。

現在、壁が必要ない場合、プログラムは機能しないことに注意してください。このケースを処理するには、+ 3文字になります。必要かどうかわかりません。

また、これはO(2^n)アルゴリズムであることに注意してくださいn。ここで、空のスポットの数です。そのため、中央に1つの野営地がある15x15の完全に空のボードの場合、これは完了するまで2^(15*15-1)= 2.6959947e+67反復を必要とします。これは実際に非常に長い時間になるでしょう!


1

グルーヴィー:841 805 754

i=new File("city.txt").getText()
x=i[2] as int
y=i[0] as int
m=i[4..i.length()-1].replaceAll('\n','').toList()
print r(m,0)
def r(m,n){if(f(m))return n;c=2e9;g(m).each{p=r(it,n+1);if(p<c)c=p;};return c;}
def f(m){u=[];u.addAll(m);for(i in 0..(x*y)){for(l in 0..m.size()-1){n(l,u);s(l,u);e(l,u);w(l,u);}};m.count('o')==u.count('o')}
def n(i,m){q=i-x;if((((q>=0)&(m[q]=='!'))|(q<0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def s(i,m){q=i+x;if((((q>=0)&(m[q]=='!'))|(q<0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def e(i,m){q=i+1;if((((q%x!=0)&(m[q]=='!'))|(q%x==0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def w(i,m){q=i-1;if((((i%x!=0)&(m[q]=='!'))|(i%x==0))&m[i]!='x'&m[i]!='W'){m[i]='!'}}
def g(m){v=[];m.eachWithIndex{t,i->if(t=='.'){n=[];n.addAll(m);n[i]='W';v<<n}};return v}

ゴルフをしていない:

def i = new File("city.txt").getText()
x=i[2].toInteger()
y=i[0].toInteger()
def m=i[4..i.length()-1].replaceAll('\n','').toList()
println r(m, 0)

def r(m, n){
    if(f(m)) return n
    def c = Integer.MAX_VALUE

    getAllMoves(m).each{ it -> 
        def r = r(it, n+1)
        if(r < c) c = r
    }
    return c;
}

def f(m){
    def t = []
    t.addAll(m)
    for(i in 0..(x*y)){
        for(l in 0..m.size()-1){
            n(l,t);s(l,t);e(l,t);w(l,t);
        }
    }
    m.count('o')==t.count('o')
}

def n(i,m){
    def t = i-x;
    if( ( ( (t >= 0) && (m[t]=='!') ) || (t < 0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    }
}

def s(i,m){
    def t = i+x;
    if( ( ( (t >= 0) && (m[t]=='!') ) || (t < 0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    }
}

def e(i,m){
    def t = i+1;
    if( ( ( (t%x!=0) && (m[t]=='!') ) || (t%x==0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    } 
}

def w(i,m){
    def t = i-1;
    if( ( ( (i%x!=0) && (m[t]=='!') ) || (i%x==0)) && m[i]!='x' && m[i]!='W'){
        m[i]='!'
    }
}

def getAllMoves(m){
    def moves = []
    m.eachWithIndex { t, i ->
        if(t=='.'){
            def newList = []
            newList.addAll(m)
            newList[i]='W'
            moves << newList
        }
    }
    return moves
}

さらに多くのゴルフが来ます...

解決策がない場合は2E9を返します。


0

Dyalog APL、91 バイト

⊃∊{1∊a[⍸×{(×d)∧s 3∨/3∨⌿⍵}⍣≡4=d←0@⍵⊢a]:⍬⋄≢⍵}¨c[⍋≢¨c←(,⍳2⊣¨b)/¨⊂b←⍸2=a←(s←(4,4,⍨⍉)⍣2)'xo.'⍳⎕]

仮定⎕IO=0、v16.0(@および)の機能を使用し、実行時間は.-s の数で指数関数的

入力を評価し、文字の行列でなければなりません

'xo.'⍳ 置き換えx、0とo1で、. 2で、及び3と他のすべて

s←(4,4,⍨⍉)⍣2 行列を4で囲む関数

a← 4で囲まれた数値行列を変数に割り当てます a

b←⍸2= b 2の座標ペアのリストです(つまり、 . -s)が

(,⍳2⊣¨b)/¨⊂b の要素のすべての組み合わせを生成する b

c[⍋≢¨c←...] サイズで並べ替えます

{... :⍬⋄≢⍵}¨ 組み合わせごとに、何かをチェックし、その長さまたは空のリストを返します

⊃∊ 最初の空でない結果

d←0@⍵⊢a da 0に置き換えいくつかの要素に

4= ブール行列の作成-4はどこにありますか?すなわち、追加したボーダー

{...}⍣≡{}結果が安定 するまで関数を適用し続けます

3∨/3∨⌿⍵ 「ブール型」または各要素とその近傍

s 結果は小さくなるので、境界線を再作成しましょう

(×d)∧ の非ゼロ要素を適用します d(非壁)の非ブールマスクとして適用する

a[⍸× ...] 何で aブール行列の1対応するですか?

1∊ 1、すなわちo野営地はありますか?

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