아일랜드 골프 # 2 : 편심 소라


19

이것은 일련의 아일랜드 골프 도전에서 두 번째입니다. 이전 도전

두 개의 은둔이 무인도에 도착했습니다. 그들은 고독을 찾아 왔기 때문에 가능한 한 멀리 떨어져 있기를 원합니다. 그들은 그들 사이의 도보 거리를 최대화하기 위해 오두막을 어디에 만들어야합니까?

관련 독서

입력

입력 내용은 토지와 물을 나타내는 두 문자로 구성된 직사각형 격자입니다. 아래 예에서 land is #and water is .이지만 원하는 두 개의 다른 문자를 대체 할 수 있습니다.

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

항상 최소 2 개의 랜드 타일이 있습니다. 랜드 타일은 모두 연속적입니다 (즉, 하나의 섬만 있습니다). 물 타일도 연속적입니다 (예 : 호수가 없음). 격자의 외부 경계는 모두 물 타일입니다. 랜드 타일은 대각선으로 연결 되지 않습니다 . 예를 들어

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

산출

코드는 두 개의 오두막 위치가 표시된 동일한 그리드를 출력해야 합니다. 아래 예에서 오두막 위치는 X로 표시되어 있지만 토지 및 물 문자와 구별되는 한 문자를 대체 할 수 있습니다.

오두막 위치는 2 개의 랜드 타일이어야하며, 그 사이 의 도보 거리 를 최대화하기 위해 선택 됩니다. 우리는 보행 거리를 두 지점 사이의 가장 짧은 경로의 길이, 전체적으로 육지에서 정의합니다. 랜드 타일은 수평 또는 수직으로 인접하지만 대각선은 아닙니다 .

위의 섬에 가능한 해결책 :

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

이 두 지점 사이의 도보 거리는 11이며이 섬의 두 지점 사이의 최대 거리입니다. 다른 거리 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

도보 거리는 맨해튼 거리입니까?
Sarge Borsch

@SargeBorsch 밀접하게 관련되어 있지만 항상 같은 것은 아닙니다. 맨해튼 거리는 Δx + Δy에 불과하지만 바다 타일을 걸을 수 없기 때문에 도보 거리가 길어질 수 있습니다. (예를 들어, 섹션 'A'의 마지막 예를 참조하십시오. 두 X 사이의 맨해튼 거리는 6이지만 나선을 따르는 보행 거리는 22입니다.)
DLosc

답변:


5

파이썬 3, 249246 바이트

DLosc 덕분에 3 바이트가 줄었습니다.

입력 및 출력은 단일 문자열이며 '.', '@'및 '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로 이동하여 경로를 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.