Island Golf # 2: The Eccentric Hermits


19

Questo è il secondo di una serie di sfide Island Golf. Sfida precedente

Due eremiti sono arrivati ​​su un'isola deserta. Poiché sono venuti in cerca di solitudine, desiderano vivere il più lontano possibile l'uno dall'altro. Dove dovrebbero costruire le loro capanne per massimizzare la distanza a piedi tra loro?

Lettura correlata

Ingresso

Il tuo input sarà una griglia rettangolare composta da due caratteri, che rappresentano terra e acqua. Negli esempi seguenti, la terra è #e l'acqua è ., ma puoi sostituire due caratteri distinti che desideri.

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

Ci saranno sempre almeno due tessere terra. Le tessere terra saranno tutte contigue (cioè c'è solo un'isola). Le tessere dell'acqua saranno anche contigue (cioè non ci sono laghi). Il bordo esterno della griglia sarà costituito da piastrelle d'acqua. Le tessere terra non saranno collegate in diagonale: cioè non vedrai mai qualcosa di simile

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

Produzione

Il codice deve generare la stessa griglia, con due posizioni di capanna contrassegnate su di essa. Negli esempi seguenti, le posizioni delle capanne sono contrassegnate con X, ma puoi sostituire qualsiasi personaggio purché sia ​​distinto dai tuoi personaggi terra e acqua.

Le posizioni delle capanne devono essere due tessere terra, scelte in modo da massimizzare la distanza percorribile tra loro. Definiamo la distanza percorribile come la lunghezza del percorso più breve, interamente a terra, tra i due punti. Le tessere terra sono considerate adiacenti in orizzontale o in verticale, ma non in diagonale.

Una possibile soluzione per l'isola sopra:

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

La distanza a piedi tra questi due punti è 11, che è la distanza massima tra due punti qualsiasi su quest'isola. Esiste un'altra soluzione distance-11:

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

Dettagli

La tua soluzione può essere un programma completo o una funzione . Uno dei metodi di input e output predefiniti è accettabile.

L'input e l'output possono essere una stringa su più righe, un elenco di stringhe o un array 2D / un elenco nidificato di caratteri / stringhe a carattere singolo. L'output potrebbe (facoltativamente) avere una sola riga finale nuova. Come accennato in precedenza, è possibile utilizzare tre caratteri distinti al posto di #.X(specificare nella presentazione quali caratteri si stanno utilizzando).

Casi test

A. Isole con posizioni di capanne uniche:

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

....
.XX.
....

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

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

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

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

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

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

B. Esempio di isola con molteplici possibili soluzioni:

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

Possibili uscite:

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

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

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

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

C. Caso di prova di grandi dimensioni come sostanza


Questo è : vince il codice più corto in ogni lingua.


2
Queste sono grandi sfide (mi piace soprattutto non dover fare alcun controllo dei limiti!): Non vedo l'ora che arrivi il prossimo!
VisualMelon

a piedi è la distanza di manhattan?
Sarge Borsch,

@SargeBorsch Strettamente correlato, ma non sempre lo stesso. La distanza di Manhattan è solo Δx + Δy, ma la distanza a piedi potrebbe essere più lunga perché non puoi camminare attraverso le piastrelle dell'oceano. (Vedi l'ultimo esempio nella sezione 'A', per esempio. La distanza di Manhattan tra le due X è 6, ma la distanza a piedi - seguendo la spirale - è 22.)
DLosc

Risposte:


5

Python 3, 249 246 byte

Eliminato 3 byte, grazie DLosc.

Input e output sono stringhe singole, con '.', '@' E 'X' che rappresentano rispettivamente acqua, capanne e terra.

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

Versione precedente:

L'input è una singola stringa, con '.' e '#' che rappresentano rispettivamente acqua e terra. 'X' rappresenta le capanne nell'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:]

Spiegazione:

Fondamentalmente sta facendo una prima ricerca ampia da ogni possibile punto di partenza allo stesso tempo. Mantieni un dizionario, d, delle lunghezze del percorso digitate all'inizio e alla fine del percorso, ad es. D [(k, i)] è la distanza da k a i. Quindi scorrere le chiavi del dizionario, d, e creare un nuovo dizionario, u, con percorsi più lunghi di 1 unità spostando l'unità del punto finale 1 su N, S, E, W, ad es. U [(k, i + 1)] = d [(k, i)] + 1. Non includere percorsi che sono già in d. Se non sei vuoto, aggiungi i nuovi percorsi più lunghi ae ripeti. Quando sei vuoto, ciò significa che non è possibile creare più percorsi. Ora d contiene tutti i percorsi possibili e le loro lunghezze. Quindi è solo una questione di ottenere la chiave con il percorso più lungo.

Versione meno giocata, commentata:

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

Facciamo rotolare la palla ...

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

Provalo online

Programma completo, legge da STDIN, scrive su STDOUT. Supera semplicemente ogni cella ed esegue un BFS per calcolare la cella più lontana, registrando entrambe se è la più lontana in assoluto. Niente di veramente, e frustrantemente poco riesco a trovare al golf.

Codice formattato e commentato:

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
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.