Острів Гольф №2: Ексцентричні пустельники


19

Це другий у серії викликів Island Golf. Попередній виклик

Два пустельники прибули на безлюдний острів. Оскільки вони прийшли шукати усамітнення, вони бажають жити якнайдалі один від одного. Де вони повинні будувати свої хати, щоб максимально збільшити відстань між ними?

Пов'язане читання

Вхідні дані

Вашим входом буде прямокутна сітка, що складається з двох символів, що представляють землю та воду. У наведених нижче прикладах земля є, #а вода є ., але ви можете замінити будь-які два символи, які ви хочете.

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

Завжди буде як мінімум дві наземні плитки. Усі суходольні плитки будуть суміжними (тобто є лише один острів). Водяні плитки також будуть суміжними (тобто озер немає). Зовнішня межа сітки - це водопровідна плитка. Земляна плитка не буде з'єднана по діагоналі: тобто ви ніколи не побачите чогось подібного

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

Вихідні дані

Ваш код повинен виводити ту саму сітку з двома місцями хат на ній. У наведених нижче прикладах місця розташування хат позначені символом X, але ви можете замінити будь-який символ, якщо він відрізняється від ваших знаків суші та води.

Місце розташування хатин повинно бути двома наземними плитками, підібраними так, щоб максимально збільшити відстань між ними. Ми визначаємо пішохідну відстань як довжину найкоротшого шляху, цілком по суші, між двома точками. Земельні плитки вважаються суміжними по горизонталі або вертикалі, але не по діагоналі.

Можливе рішення для вищевказаного острова:

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

Відстань між цими двома точками становить 11, що є найбільшою відстані між двома точками на цьому острові. Є ще одне рішення-11:

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

Деталі

Ваше рішення може бути повноцінною програмою або функцією . Будь-який із методів введення та виводу за замовчуванням є прийнятним.

Вхід і вихід можуть бути багаторядковим рядком, списком рядків або 2D-масивом / вкладеним списком символів / односимвольних рядків. Ваш висновок може (необов'язково) мати один зворотний новий рядок. Як було сказано вище, ви можете використовувати будь-які три різних символи замість #.X(будь-ласка, вкажіть у поданні, які символи ви використовуєте).

Тестові справи

А. Острови з унікальними місцями розміщення хат:

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

....
.XX.
....

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

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

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

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

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

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

Б. Приклад острова з кількома можливими рішеннями:

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

Можливі виходи:

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

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

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

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

C. Великий тестовий випадок як суть


Це : виграє найкоротший код на кожній мові.


2
Це великі маленькі виклики (особливо мені подобається не робити перевірки меж!): З нетерпінням чекаю наступного!
VisualMelon

пішохідна відстань - відстань на Манхеттені?
Sarge Borsch

@SargeBorsch Тісно пов'язані, але не завжди однакові. Манхеттенська відстань просто Δx + Δy, але пішохідна відстань може бути довшою, тому що ви не можете ходити через океанські плитки. (Дивіться, наприклад, останній приклад у розділі "А", наприклад, відстань Манхеттена між двома Х - 6, але відстань пішки - слідом за спіраллю - 22).
DLosc

Відповіді:


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 та створіть новий словник, u, із шляхами, які на 1 одиницю довші, переміщуючи кінцеву точку 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
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.