Island Golf # 2: Die exzentrischen Einsiedler

19

Dies ist die zweite in einer Reihe von Island Golf Herausforderungen. Vorherige Herausforderung

Zwei Einsiedler sind auf einer einsamen Insel angekommen. Da sie auf der Suche nach Einsamkeit kamen, möchten sie so weit wie möglich voneinander entfernt leben. Wo sollen sie ihre Hütten bauen, um die Entfernung zwischen ihnen zu maximieren?

Verwandte Lesung

Eingang

Ihre Eingabe ist ein rechteckiges Raster aus zwei Zeichen, die Land und Wasser darstellen. In den folgenden Beispielen ist Land #und Wasser ., Sie können jedoch zwei beliebige Zeichen ersetzen.

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

Es wird immer mindestens zwei Landplättchen geben. Die Landplättchen werden alle zusammenhängend sein (dh es gibt nur eine Insel). Die Wasserplättchen werden auch zusammenhängend sein (dh es gibt keine Seen). Der äußere Rand des Gitters besteht aus Wasserplättchen. Landplättchen werden nicht diagonal verbunden, dh Sie werden niemals so etwas sehen

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

Ausgabe

Ihr Code muss Ausgang das gleiche Raster, mit zwei Hütte Standorten auf sie markiert. In den folgenden Beispielen sind die Hüttenpositionen mit einem X gekennzeichnet. Sie können jedoch jedes Zeichen ersetzen, sofern es sich von Ihren Land- und Wasserzeichen unterscheidet.

Die Hüttenpositionen müssen aus zwei Landplättchen bestehen, die so gewählt sind, dass der Abstand zwischen ihnen maximiert wird . Wir definieren die Gehstrecke als die Länge des kürzesten Weges zwischen den beiden Punkten, der sich vollständig an Land befindet. Landplättchen werden horizontal oder vertikal nebeneinander, aber nicht diagonal betrachtet.

Eine mögliche Lösung für die obige Insel:

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

Die Entfernung zwischen diesen beiden Punkten beträgt 11, was die größte Entfernung zwischen zwei Punkten auf dieser Insel darstellt. Es gibt noch eine andere Lösung mit Abstand 11:

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

Einzelheiten

Ihre Lösung kann ein vollständiges Programm oder eine Funktion sein . Alle Standardeingabe- und -ausgabemethoden sind zulässig.

Ihre Eingabe und Ausgabe kann eine mehrzeilige Zeichenfolge, eine Liste von Zeichenfolgen oder ein 2D-Array / eine verschachtelte Liste von Zeichen / Einzelzeichenfolgen sein. Ihre Ausgabe kann (optional) eine einzelne nachgestellte Zeile enthalten. Wie oben erwähnt, können Sie drei verschiedene Zeichen anstelle von verwenden #.X(bitte geben Sie in Ihrer Übermittlung an, welche Zeichen Sie verwenden).

Testfälle

A. Inseln mit einzigartigen Hüttenplätzen:

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

....
.XX.
....

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

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

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

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

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

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

B. Beispiel einer Insel mit mehreren möglichen Lösungen:

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

Mögliche Ausgaben:

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

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

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

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

C. Großer Testfall als Kern


Das ist : Der kürzeste Code in jeder Sprache gewinnt.

DLosc
quelle
2
Dies sind großartige kleine Herausforderungen (ich mag es besonders, keine Grenzen überprüfen zu müssen!): Ich freue mich auf die nächste!
VisualMelon
zu fuß ist manhattan entfernung?
Sarge Borsch
@SargeBorsch Eng verwandt, aber nicht immer gleich. Die Entfernung in Manhattan beträgt nur Δx + Δy, die Gehstrecke kann jedoch länger sein, da Sie nicht über Ozeankacheln laufen können. (Siehe zum Beispiel das letzte Beispiel in Abschnitt 'A'. Der Manhattan-Abstand zwischen den beiden X beträgt 6, aber der Fußweg - der Spirale folgend - beträgt 22.)
DLosc

Antworten:

5

Python 3, 249 246 Bytes

3 Bytes gespart, danke DLosc.

Eingabe und Ausgabe sind einzelne Zeichenfolgen, wobei '.', '@' Und 'X' Wasser, Hütten bzw. Land darstellen.

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

Vorherige Version:

Die Eingabe ist eine einzelne Zeichenfolge mit '.' und '#' stehen für Wasser bzw. Land. 'X' steht für die Hütten in der Ausgabe.

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

Erläuterung:

Im Grunde genommen wird eine umfassende erste Suche von jedem möglichen Startpunkt zur gleichen Zeit durchgeführt. Behalten Sie ein Wörterbuch d der Pfadlängen bei, das durch den Anfang und das Ende des Pfades festgelegt ist, z. B. ist d [(k, i)] der Abstand von k zu i. Dann iterieren Sie über die Schlüssel im Wörterbuch d und erstellen ein neues Wörterbuch u mit Pfaden, die 1 Einheit länger sind, indem Sie den Endpunkt 1 Einheit auf N, S, E, W verschieben, z. B. u [(k, i + 1)] = d [(k, i)] + 1. Schließen Sie keine Pfade ein, die bereits in d enthalten sind. Wenn u nicht leer ist, fügen Sie die neuen längeren Pfade zu d hinzu und wiederholen Sie den Vorgang. Wenn u leer ist, können keine Pfade mehr erstellt werden. Jetzt enthält d alle möglichen Pfade und ihre Längen. Es geht also nur darum, den Schlüssel mit dem längsten Weg zu finden.

Weniger Golf, kommentierte Version:

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
quelle
3

C #, 387 Bytes

Lass uns die Kugel ins Rollen bringen...

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

Probieren Sie es online

Komplettes Programm, liest aus STDIN, schreibt nach STDOUT. Es geht einfach über jede Zelle und führt ein BFS aus, um die am weitesten entfernte Zelle zu berechnen, wobei beide aufgezeichnet werden, wenn es die am weitesten entfernte in der Aufzeichnung ist. Nichts wirklich, und frustrierend wenig finde ich zum Golfen.

Formatierter und kommentierter Code:

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
quelle