Island Golf # 2: The Herment Eksentrik

19

Ini adalah yang kedua dari serangkaian tantangan Island Golf. Tantangan sebelumnya

Dua pertapa telah tiba di pulau terpencil. Karena mereka datang mencari kesendirian, mereka ingin hidup sejauh mungkin dari satu sama lain. Di mana mereka harus membangun gubuk mereka untuk memaksimalkan jarak berjalan di antara mereka?

Bacaan terkait

Memasukkan

Input Anda akan berupa kotak persegi panjang yang terdiri dari dua karakter, mewakili tanah dan air. Dalam contoh di bawah ini, tanah adalah #dan air. , tetapi Anda dapat mengganti dua karakter berbeda yang Anda inginkan.

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

Akan selalu ada setidaknya dua tegel tanah. Ubin tanah semuanya akan bersebelahan (yaitu hanya ada satu pulau). Ubin air juga akan bersebelahan (yaitu tidak ada danau). Perbatasan luar dari grid semua akan menjadi ubin air. Ubin tanah tidak akan akan terhubung secara diagonal: yaitu, Anda tidak akan pernah melihat sesuatu seperti itu

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

Keluaran

Kode Anda harus menampilkan kisi yang sama, dengan dua lokasi pondok ditandai di atasnya. Pada contoh di bawah ini, lokasi pondok ditandai dengan X, tetapi Anda dapat mengganti karakter apa pun asalkan berbeda dengan karakter tanah dan air Anda.

Lokasi pondok harus dua ubin tanah, dipilih untuk memaksimalkan jarak berjalan di antara mereka. Kami mendefinisikan jarak berjalan sebagai panjang jalur terpendek, seluruhnya di darat, antara dua titik. Ubin tanah dianggap berdekatan secara horizontal atau vertikal, tetapi tidak secara diagonal.

Solusi yang memungkinkan untuk pulau di atas:

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

Jarak berjalan antara dua titik ini adalah 11, yang merupakan jarak terbesar antara dua titik di pulau ini. Ada solusi lain jarak-11:

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

Detail

Solusi Anda mungkin merupakan program atau fungsi lengkap . Salah satu metode input dan output default yang dapat diterima.

Input dan output Anda dapat berupa string multiline, daftar string, atau array 2D / daftar karakter yang bersarang / string karakter tunggal. Output Anda mungkin (secara opsional) memiliki satu baris baru. Seperti disebutkan di atas, Anda dapat menggunakan tiga karakter berbeda sebagai pengganti #.X(harap tentukan dalam kiriman Anda karakter mana yang Anda gunakan).

Uji kasus

A. Kepulauan dengan penempatan gubuk unik:

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

....
.XX.
....

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

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

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

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

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

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

B. Contoh pulau dengan beberapa solusi yang memungkinkan:

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

Output yang mungkin:

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

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

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

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

C. Kasus uji besar sebagai Intisari


Ini adalah : kode terpendek dalam setiap bahasa menang.

DLosc
sumber
2
Ini adalah tantangan kecil yang hebat (saya terutama suka tidak harus melakukan pemeriksaan batas!): Menantikan yang berikutnya!
VisualMelon
jarak berjalan kaki adalah jarak manhattan?
Sarge Borsch
@SargeBorsch Berhubungan erat, tetapi tidak selalu sama. Jarak Manhattan hanya +x + Δy, tetapi jarak berjalan kaki mungkin lebih lama karena Anda tidak dapat berjalan melintasi ubin laut. (Lihat contoh terakhir di bagian 'A', misalnya. Jarak Manhattan antara kedua X adalah 6, tetapi jarak berjalan - mengikuti spiral - adalah 22.)
DLosc

Jawaban:

5

Python 3, 249 246 byte

Dicukur 3 byte, terima kasih DLosc.

Input dan output adalah string tunggal, dengan '.', '@', Dan 'X' masing-masing mewakili air, pondok, dan tanah.

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

Versi sebelumnya:

Input adalah string tunggal, dengan '.' dan '#' masing-masing mewakili air dan tanah. 'X' mewakili gubuk di output.

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

Penjelasan:

Ini pada dasarnya melakukan pencarian pertama yang luas dari setiap titik awal yang memungkinkan pada saat yang sama. Menyimpan kamus, d, panjang lintasan yang dikunci oleh awal dan akhir lintasan, misalnya, d [(k, i)] adalah jarak dari k ke i. Kemudian beralihlah ke tombol dalam kamus, d, dan buat kamus baru, u, dengan jalur yang 1 unit lebih panjang dengan memindahkan titik akhir 1 unit ke N, S, E, W, misalnya, u [(k, i + 1)] = d [(k, i)] + 1. Jangan sertakan path yang sudah ada di d. Jika Anda tidak kosong, maka tambahkan path baru yang lebih panjang ke d dan ulangi. Ketika kamu kosong, itu berarti tidak ada lagi jalan yang bisa dibuat. Sekarang d berisi semua jalur yang mungkin dan panjangnya. Jadi itu hanya masalah mendapatkan kunci dengan jalur terpanjang.

Versi kurang golf, berkomentar:

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.
RootTwo
sumber
3

C #, 387 byte

Mari bola bergulir ...

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

Cobalah secara Online

Program yang lengkap, dibaca dari STDIN, menulis ke STDOUT. Ini hanya melewati setiap sel, dan menjalankan BFS untuk menghitung sel terjauh, merekam keduanya jika itu adalah yang terjauh pada catatan. Tidak ada yang benar-benar terjadi, dan sedikit sekali yang bisa saya temukan untuk bermain golf.

Kode yang diformat dan dikomentari:

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
    }
}
VisualMelon
sumber