アイランドゴルフ#2:風変わりな隠者


19

これは、一連のアイランドゴルフチャレンジの2番目です。前の挑戦

2つの隠者が砂漠の島に到着しました。彼らは孤独を求めてやって来たので、彼らはお互いにできるだけ遠くに住みたいと思っています。彼らは彼らの間の歩行距離を最大にするために彼らの小屋をどこに建てるべきですか?

関連読書

入力

入力は、土地と水を表す2つの文字で構成される長方形のグリッドになります。以下の例では、土地はで#あり、水はです.。ただし、任意の2つの異なるキャラクターを使用できます。

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

常に少なくとも2つの土地タイルがあります。土地のタイルはすべて連続しています(つまり、島は1つだけです)。水タイルも連続しています(つまり、湖はありません)。グリッドの外側の境界線はすべて水タイルになります。ランドタイルは斜めに接続されません。つまり、次のようなものは表示されません。

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

出力

コードは、2つの小屋の場所がマークされた同じグリッドを出力する必要があります。以下の例では、小屋の場所にXのマークが付けられていますが、土地や水のキャラクターと区別できる限り、任意のキャラクターに置き換えることができます。

小屋の場所は、それらの間の歩行距離を最大化するように選択された2つの土地タイルでなければなりません。歩行距離は、2つのポイント間の完全な陸上の最短経路の長さとして定義されます。ランドタイルは、水平方向または垂直方向に隣接していると見なされますが斜めではありません

上記の島の可能な解決策:

...........
...X#......
..#####....
..#######..
.#########.
...#######.
...#####.X.
....####...
...........

これらの2つのポイント間の歩行距離は11で、この島の任意の2つのポイント間の最大距離です。別のdistance-11ソリューションがあります。

...........
...##......
..X####....
..#######..
.#########.
...#######.
...#####.X.
....####...
...........

詳細

あなたの解決策は、完全なプログラムまたは機能かもしれません。いずれかのデフォルトの入力と出力の方法が許容されています。

入力と出力は、複数行の文字列、文字列のリスト、または2D配列/文字のネストされたリスト/単一文字の文字列です。出力には、(オプションで)単一の末尾改行がある場合があります。上記のように、代わりに3つの異なる文字#.Xを使用できます(使用する文字を提出時に指定してください)。

テストケース

A.ユニークな小屋の配置がある島:

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

....
.XX.
....

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

......
......
..X#..
...X..
......
......

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

........
.#####..
.##..##.
.#..###.
.#X..#X.
........

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

.........
.#####.X.
.#...#.#.
.#.X##.#.
.#.....#.
.#######.
.........

B.複数の可能な解決策がある島の例:

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

可能な出力:

........
....#X..
...####.
..###...
.#####..
.X####..
..##....
........

........
....#X..
...####.
..###...
.#####..
.#####..
..X#....
........

........
....##..
...###X.
..###...
.#####..
.X####..
..##....
........

........
....##..
...###X.
..###...
.#####..
.#####..
..X#....
........

C. 要点としての大規模なテストケース


これはです。各言語で最も短いコードが優先されます。


2
これらは非常に小さな挑戦です(特に境界チェックをする必要がないのが好きです!):次のものを楽しみにしています!
VisualMelon

徒歩距離はマンハッタン距離ですか?
セージボルシュ

@SargeBorsch密接に関連していますが、常に同じではありません。マンハッタンの距離は、Δx+Δyだけですが、海のタイルの上を歩くことができないため、歩く距離が長くなる場合があります。(たとえば、セクション「A」の最後の例を参照してください。2つのX間のマンハッタン距離は6ですが、スパイラルに続く歩行距離は22です。)
DLosc

回答:


5

Python 3、249 246バイト

DLoscに感謝します。

入力と出力はそれぞれ「。」、「@」、および「X」が水、小屋、および土地を表す単一の文字列です。

A='@'
def f(s):
 w=s.find('\n')+1;d=u={(k,k):0for k,c in enumerate(s)if A<c}
 while u:d.update(u);u={(k,j):d[(k,i)]+1for k,i in d for j in{i+1,i+w,i-1,i-w}if A<s[j]and(k,j)not in d}
 k,j=sorted(max(d,key=d.get))
 return s[:k]+A+s[k+1:j]+A+s[j+1:]

以前のバージョン:

入力は単一の文字列で、「。」が付きます 「#」はそれぞれ水と土地を表します。「X」は出力の小屋を表します。

def f(s):
 w=s.find('\n')+1;d=u={(k,k):0for k,c in enumerate(s)if'#'==c}
 while u:d.update(u);u={(k,j):d[(k,i)]+1 for k,i in d for j in{i+1,i+w,i-1,i-w}if'#'==s[j]and(k,j)not in d}
 k,j=sorted(max(d,key=d.get))
 return s[:k]+'X'+s[k+1:j]+'X'+s[j+1:]

説明:

基本的に、可能なすべての開始点から同時に幅優先検索を実行しています。パスの開始と終了をキーとするパスの長さの辞書dを保持します。たとえば、d [(k、i)]はkからiまでの距離です。次に、辞書dのキーを反復処理し、エンドポイントをN、S、E、Wに1単位移動することにより、1単位のパスで新しい辞書uを作成します。たとえば、u [(k、 i + 1)] = d [(k、i)] + 1.すでにdにあるパスを含めないでください。uが空でない場合、dに新しい長いパスを追加して繰り返します。uが空の場合、これ以上パスを作成できないことを意味します。これで、dにはすべての可能なパスとその長さが含まれます。したがって、最も長いパスでキーを取得するだけです。

以下のゴルフ、コメント版:

def f(s):
  w=s.find('\n')+1                    # width of a row, or a move N or S

  d = {}                              # dictionary of all the paths.
                                      # The key is a tuple (k,j) and the
                                      # value is the distance from k to j.
  for k,c in enumerate(s):            # Initialize. Distance from k to k is 0
    if'#'==c:                         # Only do land.
      d[(k,k)] = 0

  u = d                               # dictionary of new paths. initialize it to d
                                      # so loop is entered. first d.update is
                                      # basically a NOP

  while u:                            # while there are new paths
    d.update(u)                       # add the new paths to the dict of old paths
    u={}                              #
    for k,i in d:                     # iterate over the known paths. k is the start, i is the end
      for j in{i+1,i+w,i-1,i-w}:      # iterate over squares 1 move to the E,S,W,N from i
        if'#'==s[j]and(k,j)not in d:  # if it's still land, and the path (k,j) isn't already in d,
          u[(k,j)] = d[(k,i)]+1       # then add the new path to u

  k,j=sorted(max(d,key=d.get))        # find the longest path

  return s[:k]+'X'+s[k+1:j]+'X'+s[j+1:]  # X marks the endpoints.

3

C#、387バイト

ボールを転がしてみましょう...

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z,n,q,h,b=0,c,a,i=0,j=0;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L+="\n";for(z=H;z-->0;){int[]S=new int[H],Q=new int[H*8];for(Q[h=q=0]=z;q<=h;)if((c=S[n=Q[q++]]-1)<0&D[S[n]=n]==35)for(a=4;a-->0;b=c<b?c+(i=z)*(j=n)*0:b)S[Q[++h]=new[]{1,-1,W,-W}[a]+n]=S[Q[h]]<1?c:1;}for(;++z<H;)C.Write(z==i|z==j?'X':D[z]);}}

オンラインで試す

完全なプログラム、STDINからの読み取り、STDOUTへの書き込み。各セルを単純に調べ、BFSを実行して最も遠いセルを計算し、記録上で最も遠い場合は両方を記録します。本当に何もありませんし、イライラするほどゴルフを見つけることもできません。

書式設定されコメントされたコード:

using C=System.Console;

class P
{
    // \n 10
    // \r 13
    // . 46
    // # 35
    // x 88

    static void Main()
    {
        string D="", // map
            L; // line of input

        int W=0, // width
            H=0, // length
            z, // outer position
            n, // next position to expand
            q, // queue position pointer
            h, // queue head pointer
            b=0, // best
            c, // distance to this cell (negative)
            a, // counter
            i=0, // hermit 1 pos
            j=0; // hermit 2 pos

        for(;(L=C.ReadLine())!=null; // read a line, while we can
                H+=W=L.Length) // record the width, and add to length
            D+=L+="\n"; // add a newline, and add the line to the map

        for(z=H;z-->0;) // for each cell
        {
            int[]S=new int[H], // 'seen' >0 -> seen, else it is the distance we have found to it
                Q=new int[H*8]; // due queue (fewer than H*4 expantions, two ints each)

            // standard BFS
            for(Q[h=q=0] // reset currect 
                =z; // expand z first
                q<=h;)
                if((c=S[n=Q[q++]]-1)<0& // record 'seen', and check we havn't been seen
                    D[S[n]=n]==35) // mark as seen, and check we are a hash #
                    // 'move'
                    for(a=4;a-->0; // for each of the 4 neighbours
                            b=c<b? // if we have beaten the best
                            c+(i=z)*(j=n)*0: // set new best, record hermit positions
                            b)
                        S[Q[++h]=new[]{1,-1,W,-W}[a]+n]= // queue it for expantion
                        S[Q[h]]<1? // not seen? (this is BFS, don't need to check c is less thatn S[l+n]
                        c: // distance
                        1; // mark as seen (means it won't actually be expanded)
        }

        // z = -1
        for(;++z<H;) // for each cell
            C.Write(z==i|z==j?'X':D[z]); // print either the original char, or X if it is a hermit's home
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.