Đảo Golf # 2: Những kẻ lập dị


19

Đây là lần thứ hai trong một loạt các thử thách Island Golf. Thử thách trước

Hai ẩn sĩ đã đến trên một hòn đảo sa mạc. Vì họ tìm kiếm sự cô độc, họ muốn sống càng xa nhau càng tốt. Họ nên xây dựng những túp lều của mình ở đâu để tối đa hóa khoảng cách đi bộ giữa chúng?

Đọc liên quan

Đầu vào

Đầu vào của bạn sẽ là một lưới hình chữ nhật bao gồm hai ký tự, đại diện cho đất và nước. Trong các ví dụ dưới đây, đất #và nước là ., nhưng bạn có thể thay thế bất kỳ hai ký tự riêng biệt nào bạn muốn.

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

Sẽ luôn có ít nhất hai gạch đất. Tất cả các ô đất sẽ liền kề nhau (tức là chỉ có một hòn đảo). Các gạch nước cũng sẽ tiếp giáp nhau (tức là không có hồ). Đường viền bên ngoài của lưới sẽ là gạch nước. Gạch đất sẽ không được kết nối theo đường chéo: tức là, bạn sẽ không bao giờ thấy một cái gì đó như

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

Đầu ra

Mã của bạn phải xuất ra cùng một lưới, với hai vị trí bài chòi được đánh dấu trên đó. Trong các ví dụ dưới đây, các vị trí bài chòi được đánh dấu bằng X, nhưng bạn có thể thay thế bất kỳ ký tự nào miễn là nó khác với các ký tự trên mặt đất và dưới nước của bạn.

Các vị trí bài chòi phải là hai ô đất, được chọn để tối đa hóa khoảng cách đi bộ giữa chúng. Chúng tôi xác định khoảng cách đi bộ là chiều dài của con đường ngắn nhất, hoàn toàn trên đất liền, giữa hai điểm. Gạch đất được coi là liền kề theo chiều ngang hoặc chiều dọc, nhưng không theo đường chéo.

Một giải pháp khả thi cho hòn đảo trên:

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

Khoảng cách đi bộ giữa hai điểm này là 11, đó là khoảng cách lớn nhất giữa hai điểm bất kỳ trên hòn đảo này. Có một giải pháp khoảng cách-11 khác:

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

Chi tiết

Giải pháp của bạn có thể là một chương trình đầy đủ hoặc một chức năng . Bất kỳ phương thức nhập và xuất mặc định nào đều được chấp nhận.

Đầu vào và đầu ra của bạn có thể là một chuỗi nhiều dòng, một danh sách các chuỗi hoặc một mảng 2D / danh sách các ký tự / chuỗi ký tự đơn. Đầu ra của bạn có thể (tùy chọn) có một dòng mới duy nhất. Như đã đề cập ở trên, bạn có thể sử dụng bất kỳ ba ký tự riêng biệt nào thay thế #.X(vui lòng ghi rõ trong bài gửi của bạn những ký tự bạn đang sử dụng).

Các trường hợp thử nghiệm

A. Quần đảo với các vị trí bài chòi độc đáo:

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

....
.XX.
....

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

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

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

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

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

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

B. Ví dụ về một hòn đảo có nhiều giải pháp khả thi:

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

Đầu ra có thể:

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

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

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

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

C. Trường hợp thử nghiệm lớn như một ý chính


Đây là : mã ngắn nhất trong mỗi ngôn ngữ sẽ thắng.


2
Đây là những thử thách nhỏ tuyệt vời (tôi đặc biệt thích không phải thực hiện bất kỳ kiểm tra giới hạn nào!): Mong muốn tiếp theo!
VisualMelon

khoảng cách đi bộ là khoảng cách manhattan?
Sange Borsch

@SargeBorsch Liên quan chặt chẽ, nhưng không phải lúc nào cũng giống nhau. Khoảng cách Manhattan chỉ là Δx + Δy, nhưng khoảng cách đi bộ có thể dài hơn vì bạn không thể đi bộ qua gạch biển. (Xem ví dụ cuối cùng trong phần 'A', ví dụ: Khoảng cách Manhattan giữa hai chữ X là 6, nhưng khoảng cách đi bộ - theo đường xoắn ốc - là 22.)
DLosc

Câu trả lời:


5

Python 3, 249 246 byte

Cạo đi 3 byte, cảm ơn DLosc.

Đầu vào và đầu ra là các chuỗi đơn, với '.', '@' Và 'X' tương ứng là nước, túp lều và đất.

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:]

Phiên bản trước:

Đầu vào là một chuỗi đơn, với '.' và '#' tương ứng với nước và đất. 'X' đại diện cho các túp lều ở đầu ra.

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:]

Giải trình:

Về cơ bản, nó đang thực hiện tìm kiếm đầu tiên từ mọi điểm bắt đầu có thể cùng một lúc. Giữ một từ điển, d, độ dài đường dẫn được khóa bởi điểm bắt đầu và kết thúc của đường dẫn, ví dụ: d [(k, i)] là khoảng cách từ k đến i. Sau đó lặp lại các phím trong từ điển, d và tạo một từ điển mới, u, với các đường dẫn dài hơn 1 đơn vị bằng cách di chuyển điểm cuối 1 đơn vị đến N, S, E, W, ví dụ: u [(k, i + 1)] = d [(k, i)] + 1. Không bao gồm các đường dẫn đã có trong d. Nếu u không trống, sau đó thêm các đường dẫn mới dài hơn vào d và lặp lại. Khi bạn trống, điều đó có nghĩa là không còn đường dẫn nào nữa. Bây giờ d chứa tất cả các đường dẫn có thể và độ dài của chúng. Vì vậy, nó chỉ là vấn đề nhận được chìa khóa với con đường dài nhất.

Ít chơi gôn hơn, nhận xét phiên bản:

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 byte

Hãy để bóng lăn ...

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]);}}

Dùng thử trực tuyến

Hoàn thành chương trình, đọc từ STDIN, ghi vào STDOUT. Nó chỉ đơn giản là đi qua từng ô và chạy BFS để tính toán ô xa nhất, ghi cả hai nếu nó là bản ghi xa nhất. Không có gì với nó thực sự, và bực bội một chút tôi có thể tìm thấy để chơi golf.

Mã định dạng và nhận xét:

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
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.