岛屿高尔夫2:古怪的隐士


19

这是Island Golf系列挑战中的第二次挑战。先前的挑战

两个隐士到达了一个荒岛。由于他们寻求孤独,所以他们希望彼此之间住得尽可能远。他们应该在哪里建造小屋,以使他们之间的步行距离最大化?

相关阅读

输入项

您的输入将是一个由两个字符组成的矩形网格,分别代表土地和水。在下面的示例中,土地是#,水是.,但是您可以替换任意两个不同的字符。

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

始终将至少有两个地砖。地砖将是连续的(即只有一个岛)。瓷砖也将是连续的(即没有湖泊)。网格的外边界都是水瓦片。地砖将不会以对角线连接:即,您将永远不会看到类似

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

输出量

您的代码必须输出相同的网格,并在网格上标记了两个小屋位置。在下面的示例中,小屋的位置用X标记,但是您可以替换任何字符,只要它与您的水陆字符不同即可。

小屋的位置必须为两个地砖,以选择它们之间的最大步行距离。我们将步行距离定义为两点之间完全在陆地上的最短路径的长度。地砖被视为水平或垂直相邻,但不对角。

上述岛屿的可能解决方案:

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

这两个点之间的步行距离是11,这是该岛上任何两个点之间的最大距离。还有另一个距离11解决方案:

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

细节

您的解决方案可能是完整程序或功能。任何默认的输入和输出方法都是可以接受的。

您的输入和输出可以是多行字符串,字符串列表或2D数组/嵌套的字符列表/单字符字符串。您的输出可能(可选)有一个尾随换行符。如上所述,您可以使用任何三个不同的字符来代替#.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”部分的最后一个示例。两个X之间的曼哈顿距离为6,但沿着螺旋线的步行距离为22。)
DLosc

Answers:


5

Python 3中,249个 246字节

减少了3个字节,感谢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中的键,并通过将端点1单位移至N,S,E,W,例如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
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.