Un'esperienza di punta: visita rapidamente tutte le vette


22

Mi trovo sul punto (0,0)in una mappa Hx in Wcui l'altitudine è rappresentata da cifre, ad esempio:

1132
2221
1230    # H = 3, W = 4

Mi piacerebbe sperimentare i panorami da ogni picco, che in questo caso sono le aree con altitudine 3. Tuttavia, salire su per le colline non è un compito facile e sto anche esaurendo il tempo.

Sfida

La sfida è trovare il percorso più veloce per visitare tutte le cime e tornare.

Vince il programma più breve.

Ingresso

  • H, W - altezza e larghezza della mappa (numeri interi) (facoltativo, può essere un elenco / tupla o due input interi separati)
  • La mappa, fornita come Hserie di Wcifre ( 0- 9), in qualsiasi formato conveniente (elenco 2D, stringa separata da newline, ecc.)

Produzione

  • Il tempo più breve impiegato per visitare ogni picco e tornare al punto di partenza (intero)

condizioni

  • L'altitudine di una determinata area è rappresentata da una cifra da 0a 9.
  • Il "picco" è definito dall'area con l'altitudine più alta.
  • Il percorso deve iniziare e terminare nell'area in alto a sinistra (0,0) .
  • Puoi spostarti solo nelle aree adiacenti alla tua area corrente e non puoi muoverti in diagonale.
    • Ci vogliono 3 minuti per spostarsi da un'area all'altra se non ci sono cambiamenti di altitudine.
    • Ci vogliono 11 minuti per salire; cioè, spostarsi da un'area all'altra che è esattamente l' 1unità più alta.
    • Ci vogliono 2 minuti per scendere; vale a dire, spostarsi da un'area all'altra che è esattamente 1più bassa dell'unità.
    • Non puoi spostarti in aree che sono più 1dell'unità più in alto o più in basso di dove ti trovi. (Non puoi passare da un'area con altitudine 1a un'area adiacente con altitudine, diciamo, 3)
  • Un percorso verso tutte le vette è garantito
  • Il numero massimo di picchi è 15.

Campioni

Ingresso

4 5
32445
33434
21153
12343

Produzione

96

Spiegazione

Si inizia in alto a sinistra 3. Devi visitare le due 5s che si trovano in (0,4)e (3,3)e tornare al 3in (0,0)nel più breve tempo possibile.

3  2  4->4->5
V     ^
3->3->4  3  4

2  1  1  5  3

1  2  3  4  3    # 3 + 3 + 11 + 3 + 3 + 11 = 34 minutes to visit 1st peak


3  2  4  4  5
            V
3  3  4  3  4
            V
2  1  1  5  3
         ^  V
1  2  3  4<-3    # 2 + 2 + 3 + 11 + 11 = 29 minutes to visit 2nd


3  2  4  4  5
^            
3  3  4  3  4
^            
2  1  1  5  3
^        V   
1<-2<-3<-4  3    # 2 + 2 + 2 + 2 + 11 + 11 + 3 = 33 minutes to come back

# 34 + 29 + 33 = 96 minutes total is the answer

Ingresso

2 7
6787778
5777679

Produzione

75

9
Benvenuti in PPCG e ottima prima domanda! Consiglio vivamente di cambiarlo in una domanda di golf del codice, dal momento che ci deve essere un criterio vincente obiettivo per segnare le risposte.
Deusovi,

4
Grazie per la raccomandazione, ho letto le regole nel Centro assistenza e ho modificato la domanda
cozyconemotel,

Forse la tua sfida riceverebbe più colpi se il titolo fosse migliorato. "Sfida alpinistica" forse.
DavidC,

1
cozyconemotel, ho suggerito un titolo più breve, forse più attraente per la tua sfida. Se lo desideri, sentiti libero di riportarlo all'originale. (Ci sono state 245 visualizzazioni dalla tua presentazione.)
DavidC

@DavidC Sono totalmente d'accordo. Grazie per la modifica.
cozyconemotel,

Risposte:


5

Mathematica 745 681 byte

L'idea di base è quella di fare un grafico ponderato delle possibili mosse. I pesi sono il tempo necessario per spostarsi da un luogo all'altro. Il percorso con il minor peso sarà il più veloce.

Le cifre di input sono inserite in una matrice rettangolare r by c (righe per colonne) e quindi entrano in gioco tre rappresentazioni distinte: (1) un grafico a griglia r by c, in cui ciascun vertice corrisponde a una cella della matrice, (2) (r c) da (r c) matrice di adiacenza ponderata che contiene pesi corrispondenti al tempo impiegato (2, 3 o 11 minuti) per spostarsi da una posizione (nel grafico a griglia) a un'altra e (3) una direzione , grafico di adiacenza ponderato costruito dalla matrice.

Il grafico a griglia aiuta a determinare quali celle (cioè quali vertici) sono eventualmente raggiungibili da ciascun vertice - "probabilmente raggiungibile" perché una cella vicina non deve essere solo destra, sinistra, sopra o sotto una data cella. Il valore deve inoltre trovarsi entro 1 unità di distanza dal vicino (ad esempio, un 3 non si collega a un vicino 5 o un 1). Se il vertice anon è collegato al verticeb le celle della matrice di adiacenza {a, b} e {b, a} avranno un valore di ∞. Di conseguenza, il grafico di adiacenza ponderato non avrà un bordo da a a b, né da b a a.

Il grafico di adiacenza ponderato serve a determinare la distanza minima ( GraphDistance) e il percorso più breve tra i vertici. Il percorso ottimale deve iniziare con 1, toccare ciascuno dei picchi e tornare a 1. In questo caso, "percorso più breve" non è necessariamente quello con il minor numero di mosse. È quello con il tempo complessivo più breve, misurato in pesi del bordo.


golfed

o=Sequence;v[a_<->b_,z_]:=(m_~u~q_:={Quotient[m-1,q[[2]]]+1,1+Mod[m-1, q[[2]]]};j=z[[o@@u[a,i=Dimensions@z]]];k=z[[o@@u[b,i]]];Which[j==k,{{a,b}->3,{b,a}->3},j==k-1,{{a,b}->11,{b,a}->2},j==k+1,{{a,b}->2,{b,a}->11},2<4,{{a,b}->∞, {b, a}->∞}]);w@e_:=Module[{d,x,l,y},x=Map[ToExpression,Characters/@Drop[StringSplit@e,2],{2}];d_~l~c_:=d[[2]](c[[1]]-1)+c[[2]];g_~y~p_:=(Min[Plus@@(GraphDistance[g,#,#2]&@@@#)&/@(Partition[#,2,1]&/@({1,o@@#,1}&/@Permutations@p))]);y[WeightedAdjacencyGraph[ReplacePart[ConstantArray[∞,{t=Times@@(d=Dimensions@x),t}],Flatten[#~v~x &/@Union@Flatten[EdgeList[GridGraph@Reverse@d,#<->_]&/@Range@(Times@@d),1],1]]], l[Dimensions@x, #] & /@ Position[x, Max@x]]

Forma più lunga e più leggibile

(*determines a weight (number of minutes) to go from vertex a to b and from b to a*)
weight[a_ <-> b_, dat_]:= 
  Module[{cellA,cellB,dim,valA,valB,vertexToCell},

  (*Convert graph vertex index to cell location*)
  vertexToCell[m_,dimen_]:={Quotient[m-1,dim[[2]]]+1,1+Mod[m-1,dimen[[2]]]};
     dim=Dimensions[dat];
     cellA = vertexToCell[a,dim];
     cellB = vertexToCell[b,dim];
     valA=dat[[Sequence@@cellA]];
     valB=dat[[Sequence@@cellB]];
     Which[
       valA==valB,{{a,b}-> 3,{b,a}-> 3},
       valA==valB-1,{{a,b}-> 11,{b,a}-> 2},
       valA==valB+1,{{a,b}-> 2,{b,a}-> 11},
       2<4,{{a,b}->∞,{b,a}->∞}]];

(* weights[] determines the edge weights (times to get from one position to the next), makes a graph and infers the shortest distance 
from vertex 1 to each peak and back.  It tries out all permutations of peaks and 
selects the shortest one. Finally, it returns the length (in minutes) of the shortest trip. *)

weights[str_]:=
  Module[{d,dat,neighbors,cellToVertex,peaks,z,gd},
  dat=Map[ToExpression,Characters/@Drop[StringSplit[str],2],{2}];
  cellToVertex[dim_,cell_]:=dim[[2]] (cell[[1]]-1)+cell[[2]];
  peaks[dat_]:= cellToVertex[Dimensions[dat],#]&/@Position[dat,peak =Max[dat]];

     (* to which cells should each cell be compared? neighbors[] is a function defined within weights[]. It returns a graph, g, from which graph distances will be derived in the function gd[] *)
  neighbors[dim_]:=
  Union@Flatten[EdgeList[GridGraph[Reverse@dim],#<->_]&/@Range@(Times@@dim),1];
    d=Dimensions[dat];
    m=ReplacePart[ConstantArray[∞,{t=Times@@d,t}], 
     (*substitutions=*)
    Flatten[weight[#,dat]&/@neighbors[d],1]];
    g=WeightedAdjacencyGraph[m,VertexLabels->"Name",ImageSize->Full,GraphLayout->"SpringEmbedding"];

    (* finds shortest path.  gd[] is also defined within weights[] *)
  gd[g3_,ps_]:=
    Module[{lists,pairs},
    pairs=Partition[#,2,1]&/@({1,Sequence@@#,1}&/@Permutations@ps);
    Min[Plus@@(GraphDistance[g3,#,#2]&@@@#)&/@pairs]]; 

  gd[g,peaks[dat]]]

test

weights["4 5
 32445
 33434
 21153
 12343"]

96.


weights@"2 7
 6787778
 5777679"

75.


weights@"3 4
 1132
 2221
 1230"

51.


Spiegazione

Pensa alle righe 2-5 del seguente input

"4 5
 32445
 33434
 21153
 12343"

come rappresentante una matrice con 4 righe e 5 colonne:

gridgraph

dove ogni vertice corrisponde a una cifra dall'array di input: 3 è al vertice 1, 2 è al vertice 2, 4 è al vertice 3, un altro 4 al vertice 4, 5 al vertice 5, ecc. Il grafico della griglia è solo un grezzo approssimazione del grafico a cui miriamo. Non è indirizzato. Inoltre, alcuni dei bordi non saranno disponibili. (Ricorda: non possiamo spostarci da una posizione a un'altra che è più di 1 unità di altezza sopra o sotto quella corrente.) Ma il grafico della griglia ci permette di trovare facilmente quei vertici che si trovano accanto a qualsiasi vertice scelto. Ciò riduce il numero di spigoli che dobbiamo considerare, nel primo esempio (una griglia 4 per 5), da 400 (20 * 20) a 62 (31 * 2 è il numero di spigoli nel grafico della griglia). Nello stesso esempio, solo 48 dei bordi sono operativi; 14 non lo sono.

La seguente matrice di adiacenza ponderata 20 per 20 rappresenta la distanza tra tutte le coppie di vertici dal grafico della griglia.

Il codice chiave che decide su quale numero assegnare è riportato di seguito.

Which[
      valA==valB,{{a,b}-> 3,{b,a}-> 3},
      valA==valB-1,{{a,b}-> 11,{b,a}-> 2},
      valA==valB+1,{{a,b}-> 2,{b,a}-> 11},
      2<4,{{a,b}->∞,{b,a}->∞}]

La cella {1,2} - in una indicizzazione - contiene il valore 2 perché lo spostamento dal vertice 1 al vertice 2 è in discesa. La cella {2,1} contiene 11 perché il passaggio dal vertice 2 al vertice 1 è in salita. I 3 nelle celle {1,6} e {6,1} indicano che il movimento non è né in alto né in basso. La cella {1,1} contiene ∞ perché non è connessa a se stessa.

pesi

Il grafico seguente mostra la struttura alla base dell'input sopra. Le frecce colorate mostrano il percorso ottimale dal vertice 1 ai picchi (a 5 e 14) e di nuovo a 1. Le frecce blu corrispondono a movimenti allo stesso livello (3 min); le frecce rosse indicano la salita (11 min.) e le frecce verdi indicano la discesa (2 min).

Graph2

Il percorso dal vertice 1 (cella {1,1} ai due picchi e ritorno al vertice 1:

3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3

96


0

Pyth, 92 byte

hSms@Lu.dm,bhS,@Gb+@G,hbH@G,HebG[FQ.dm,(Fb?|tsaMCb>.aJ-F@LQb1.n4@[3hT2)J*QQC.<B+]hSQd1.p.M@Q

Il formato di ingresso è un dict mappatura coordinate ad altezze: {(0, 0): 3, (0, 1): 2, (0, 2): 4, …}. Questo trova i percorsi più veloci tra tutte le coppie di punti usando l' algoritmo Floyd-Warshall , quindi minimizza il tempo totale del ciclo desiderato su tutte le permutazioni dei picchi.

Provalo online

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.