Mathematica 745 681 bytes
The basic idea is to make a weighted graph of possible moves. Weights are the time it takes to move from one place to the next. The path with the least weight will be the quickest.
The input digits are placed in an r by c (rows by columns) rectangular array and then three distinct representations come into play: (1) an r by c grid graph, where each vertex corresponds to a cell in the array, (2) (rc) by (rc) weighted adjacency matrix that holds weights corresponding to the time it takes (2, 3, or 11 minutes) to move from one location (in the grid graph) to another, and (3) a directed, weighted adjacency graph constructed from the matrix.
The grid graph helps determine which cells (i.e. which vertices) are possibly reachable from each vertex--"possibly reachable" because a neighboring cell must not only be right, left, above or below a given cell. It's value must also be within 1 unit of distance from the neighbor (e.g., a 3 does not connect to a neighboring 5 or a 1). If vertex a
is not connected to vertex b
then the adjacency matrix cells {a,b} and {b,a} will have a value of ∞. Accordingly, the weighted adjacency graph will not have an edge from a to b, nor from b to a.
The weighted adjacency graph serves to determine the minimum distance (GraphDistance
) and shortest route between any vertices. The optimal path must begin with 1, touch each of the peaks, and return to 1. In this case, "shortest route" is not necessarily the one with the fewest moves. It is the one with the shortest overall time, measured in edge weights.
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]]
Longer, more readable form
(*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]]]
Tests
weights["4 5
32445
33434
21153
12343"]
96.
weights@"2 7
6787778
5777679"
75.
weights@"3 4
1132
2221
1230"
51.
Explanation
Think of lines 2-5 of the following input
"4 5
32445
33434
21153
12343"
as representing an array with 4 rows and 5 columns:
![gridgraph](../../I/static/images/e93b14b177d078a13ac27a9b331b192657e373e20c5580f0b02f4ceb5565183b.png)
where each vertex corresponds to a digit from the input array: 3 is at vertex 1, 2 is at vertex 2, 4 is at vertex 3, another 4 at vertex 4, 5 at vertex 5, etc. The grid graph is only a rough approximation of the graph we are aiming for. It is undirected. Furthermore, some of the edges will be unavailable. (Remember: we cannot move from a position to another that is more than 1 height unit above or below the current one.) But the grid graph let's us easily find those vertices that are next to any chosen vertex. This reduces the number of edges we need to consider, in the first example (a 4 by 5 grid), from 400 (20 * 20) to 62 (31 *2 is the number of edges in the grid graph). In the same example, only 48 of the edges are operative; 14 are not.
The following 20 by 20 weighted adjacency matrix represents the distance between all pairs of vertices from the grid graph.
The key code which decides on which number to assign is below.
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}->∞}]
Cell {1,2}--in one-indexing-- contains the value 2 because the move from vertex 1 to vertex 2 is downhill.
Cell {2,1} contains 11 because the move from vertex 2 to vertex 1 is uphill.
The 3's in cells {1,6} and {6,1} signify that the movement is neither up nor down.
Cell {1,1} contains ∞ because it is not connected to itself.
![weights](../../I/static/images/061c9083c20d452ae4552870f5333f84ee7b397aeacbbcb104cc381609efd0d2.png)
The following graph shows the structure underlying the above input. The colored arrows show the optimal path from vertex 1 to the peaks (at 5 and 14) and back to 1. Blue arrows correspond to moves at the same level (3 min); red arrows mean ascent (11 min.) and green arrows indicate descent (2 min).
![graph2](../../I/static/images/62a9862f5be146aec3b5fad2a21a3aa9e278f21cb9cd3700e96fd920afb7b9e1.png)
The path from vertex 1 (cell {1,1} to the two peaks and back to vertex 1:
3 + 3 + 11 + 3 + 3 + 11 + 2 + 2 + 3 + 11 + 11 + 2 + 2 + 2 + 2 + 11 + 11 + 3
96
9Welcome to PPCG, and great first question! I highly recommend changing this to a code golf question, since there has to be an objective winning criterion to score answers. – Deusovi – 2016-01-27T10:53:53.043
4Thank you for the recommendation, I read the rules in the help center and edited the question – cozyconemotel – 2016-01-27T23:42:05.223
Perhaps your challenge would receive more hits if the title were improved. "Mountain climbing challenge" perhaps. – DavidC – 2016-07-11T04:44:12.773
1cozyconemotel, I suggested a shorter, perhaps more attractive title for your challenge. Please feel free to change it back to the original if you wish. (There have been 245 viewings since your submission.) – DavidC – 2016-07-11T12:50:21.823
@DavidC I totally agree. Thank you for the edit. – cozyconemotel – 2016-07-11T16:08:32.983