| Bytes | Lang | Time | Link |
|---|---|---|---|
| 400 | Python3 | 250928T205431Z | Ajax1234 |
| nan | PHP | 190319T172519Z | 640KB |
| 132 | APL Dyalog Extended | 190320T195753Z | voidhawk |
| 622 | Python 3 | 190320T135432Z | ABridgeT |
| 173 | JavaScript ES6 | 190318T134303Z | Arnauld |
| 233 | Python 2 | 190318T184916Z | Erik the |
Python3, 400 bytes
E=enumerate
def L(x,y,d):
q=[(x,y,[(x,y)])]
for x,y,p in q:
if(x,y)in d and'T'==d[(x,y)]:del d[(x,y)];return p
q+=[(*t,p+[t])for X,Y in[(1,0),(-1,0),(0,-1),(0,1)]if(V:=d.get(t:=(x+X,y+Y)))and V!='M'and t not in p]
def f(b):
d,r={(x,y):v for x,r in E(b)for y,v in E(r)},[]
x,y=[j for j in d if'P'==d[j]][0]
while any(j not in r for j in d if'T'==d[j])and(V:=L(x,y,d)):r+=V;x,y=V[-1]
return r
PHP, 385 335 307 270 256 bytes
function c(&$m,$x,$r=-1,$d=0){if($r<0)$r=array_search(P,$m);$m[$r]=V;if(!in_array(T,$m))die;foreach([$r%$x?$r-1:-1,$m[$r-$x]?$r-$x:-1,$m[$r+$x]?$r+$x:-1,$r%$x<$x-1?$r+1:-1]as$o=>$n)if($n>=0&$m[$n]!=M&$m[$n]!=V){echo LUDR[$o];c($m,$x,$n,$o);}echo RDUL[$d];}
Uses a recursive depth-first search to crawl the map until all treasures are found.
Input is a one-dimensional array map and number of columns, example: c( $map, 13 );.
Output is to STDOUT as L,R,U and D.
Or 242 bytes to output as numbers (but I prefer the letters).
Ungolfed
function c( &$m, $x, $r=-1, $d=0 ) {
// locate starting room ($r) on first move
if( $r < 0 )
$r = array_search( 'P', $m );
// mark square on map ($m) with V to show it has been visited
$m[ $r ] = 'V';
// end if no more treasures
if ( ! in_array( 'T', $m ) )
exit;
// generate list of adjacent squares
$dirs = [
$r % $x ? $r - 1 : -1, // Left
$m[ $r - $x ] ? $r - $x : -1, // Up
$m[ $r + $x ] ? $r + $x : -1, // Down
$r % $x < $x - 1 ? $r + 1 : -1 // Right
];
// consider valid directions for next move
foreach ( $dirs as $o => $n )
// if not a Wall or Mountain and not Visited
if ( $n >= 0 and $m[ $n ] != 'M' and $m[ $n ] != 'V' ) {
// display the direction
echo 'LUDR'[ $o ];
// and recursively keep crawling
c( $m, $x, $n, $o );
}
// reached a dead end, go back to previous square
echo 'RDUL'[ $d ]; // display the reverse direction
}
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|P| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | |T| | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | |M|M|M|T| | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | |T| | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
DDDDDRUUUUURDDRUURDDRUURDDDLDLLLDRRRRURUUUURDDDDDLRRU
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|P| | | | |M| | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | |M| | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | |T| | |M| | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M| | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
DDRUURDD
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|P|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
(no output)
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M|M|M|M|M|M|M|M|M|M|M|P|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
(no output)
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T|T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T|T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T|T|P|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T|T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T|T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|T|T|T|T|T|T|T|T|T|T|T|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
LLLLLLUURDRURDRURDRURDDDLLLLLLLDDRURDRURDRURDRURUUUURDDDDDLRRUUUUURDDDDDRUUUUU
+-+
|P|
+-+
(no output)
DDDDDRUUUUURDDDDDRUUUUURDDDDDRUUUUURDDDDDRUUUUURRRRRLLLLLDDRRRRRLLLLLDDRRRRR
Hedge Maze (an original creation)
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|P|M| |T|M| | | |M| |M|M|T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |M| |M| | |M|T|M|T| | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T| | |M| |M| |T|M|M|M| |M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M| | | |M| |M|M| | | |M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T| | |M| |M| | | | |M| |M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|M| |T| | |M|M|M|M|M| |T|
+-+-+-+-+-+-+-+-+-+-+-+-+-+
DDRRUURLDDDDLLRRDRRUULRUURURRDDLDDRRRURRUULLUDRRRUDLDDDDR
APL (Dyalog Extended), 132 bytes
Saved 16 bytes by having the function ouput 1 0,0 1,¯1 0,0 ¯1 instead of U,L,D,R. TIO link below decodes output back to letters.
I may write an explanation later, but most of the work is creating a graph in a format that the dfns path function likes, then using it to find successive shortest paths between the start and all treasures. Quite efficient, but because treasures are pathed left-to-right, top-to-bottom instead of being based on proximity, the answers are not optimal.
{z←×`/d←⍴⍵⋄g←z⍴⊂⍬⋄s t m←(⍸∘∊⍵=⊢)¨'PTM'⋄f←{(⍵∊m)∨0=⍺:⍬⋄g[⍺],←⍵}⋄h←(f`⍨,f)⋄⍬≡t⊣{2h`/⍵⊣2h`⌿⍵}x←d⍴⍳z:⍬⋄⊃,/⊃,/2-/¨{⍸x=⍵}¨¨2(g⌂path,)/s,t}
Python 3, 766 622 bytes
def f(s,W,H):
Z=enumerate;I=[("L",-1),("R",1),("D",1j),("U",-1j)];o="";P,M,T=map(lambda t:{x+y*1jfor y,l in Z(s)for x,c in Z(l)if c==t},'PMT');E=D={c:{t:0}for t,c in Z(T)}
while len(E):
E={}
for m,N in[(c+d,D[c])for c in D for _,d in I if not c+d in M]:
if 0<=m.real<W and 0<=m.imag<H:
T={t:N[t]+1for t in N if not m in D or not t in D[m]}
if any(T)or not m in D:
E[m]=T
for m in E:
if m in D:
D[m].update(E[m])
else:
D[m]=E[m]
for m in P:
if m in D:
for g in D[m]:
while D[m][g]:
for i,d in I:
if m+d in D and D[m+d][g]<D[m][g]:
o+=i;m=m+d;break
return o
Fairly certain after this that I will never win code-golf, but contributing because I enjoyed the exercise.
This version works by building a dictionary of reachable locations, with each entry being a dictionary whose keys are a unique ID for the treasure, and whose value is the shortest distance to that treasure. The code supports multiple values for P: for each one it outputs a path that collects the treasures. No optimization is attempted.. it picks the nearest treasure from its current location until all treasures are collected.
JavaScript (ES6), 187 183 173 bytes
Takes input as a matrix of characters. Returns an array of signed integers: -2 = down, -1 = right, 1 = left and 2 = up.
ff=(m,X,Y,p=[])=>/T/.test(m)?(g=u=>m.some((r,y)=>r.some((c,x)=>(r[o=c=='M'|c>u|(h=X-x)*h+(v=Y-y)*v^c!='P'?0:f(m,x,y,1/X?[...p,h+2*v]:p,r[x]=3-~r[x]),x]=c,o)))?O:g(-~u))``:O=p
Try it online! (with the output translated back to L, R, U, D)
How?
This AI:
Is definitely more artificial than intelligent.
Rushes like a mad man in the map (i.e. implements a depth-first search).
Stops as soon as there are no more treasures, but otherwise does not care about the positions of the remaining treasures. This test is done with a regular expression.
/T/.test(m)Compares the quadrance between its current position \$(X,Y)\$ and a new position \$(x,y)\$ with \$1\$ to know whether it can move there. Or tests if the cell contains
"P"if its position is not yet defined.(h = X - x) * h + (v = Y - y) * v ^ c != 'P'Writes \$4N\$ on a cell that has been visited \$N\$ times and uses this threshold combined with an internal counter \$u\$ to decide -- in a sudden flash of lucidity -- whether it should backtrack over already visited cells when everything else failed.
Python 2, 233 bytes
G=input()
e=enumerate
P=T=M=E=frozenset()
for i,k in e(G):
for j,l in e(k):exec l+'|={(i,j)}'
G={0}
c=-1
while T-G|G&M|G-E-T:
G-=G;e=list(P)[0];x=c=c+1;r=()
while x:m=x%5%4;x/=5;r+=m,;e=~-m%2*~-m+e[0],m%2*(m-2)+e[1];G|={e}
print r
Very slow. Most of the test cases would probably time out.
MPTLRUD → EMPT1302. Any other characters should be considered to be prefixes, separators or postfixes.