# Let's make a map of dungeon

Long time ago, when I was spending more time playing RPG, one of the issues what some players had, was to track party movement and to draw proper map. So I come with idea, to check how you guys come deal with this issue.

Task is to write a function, which takes as input parameter list of directions (passed as structure of your choice) ^v<>, display map of dungeon. In example for input: >>>vvv<<<^^^ output will be:

+----+               +----+
|    |               |>>>v|
| ++ |               |^++v|
| ++ |  because      |^++v|
|    |               |^<<<|
+----+               +----+


Testcases

>>>>>>vvvvv<<<<^^^>>v

+-------+
|       |
+-+---+ |
|   | |
| + | |
| +-+ |
|     |
+-----+

^^^^^vvv<<<^^vv>>>>>>>>vv>><<^^^^v>>>>v^<^

+-+
+-+| | +-++-+
| || | | ++ ++
| ++ +-+     |
|        +-+ |
+--+ +-+ +-+-+
| | |   |
+-+ +---+


As it is golf code challenge, shortest code wins.

Happy golfing.

EDIT Sorry for late edit, I didn't have much time recently.

Map is generated based on movement. It should contain only corridors which were visited during walk. Hence creating one big room won't be a valid answer.

There are three valid symbols in the map:

• | vertical wall
• | horizontal wall
• + intersection of vertical and horizontal wall.

Maximum length of the path is 255 character (but if you can, do not limit yourself).

More test cases:

 ><><><><

+--+
|  |
+--+

>^<v

+--+
|  |
|  |
+--+


I hope now everything is clear.

• You need to provide a description of the task. The two test cases aren't even handled in a way that appears consistent -- the first adds a disconnected region for no apparent reason. Sep 1, 2016 at 16:55
• Your second example has a closed-off room, which I initially thought was because the outer border should be rectangular, but then the third example disproves that idea. Please use the Sandbox to get feedback on a challenge before posting. Sep 1, 2016 at 16:57
• Excellent. I'd still suggest being explicit about how the dungeon is constructed from the movements. Sep 1, 2016 at 17:04
• What do you mean by "display map"? Is returning the map from a function allowed? Sep 1, 2016 at 17:04
• This looks interesting. Any chance of editing to get it re-opened? Things to look at in particular: from the examples, it looks like you don't mind extra whitespace around the output but it would be good to clarify. Also if you explicitly describe the wall appearance and answer milk's question it should make the question sufficiently clear. One thing I think you haven't covered is what output vvv>>^^^<< would produce (crosses? pipes?)
– Dave
Sep 4, 2016 at 10:41

## Javascript (ES6), 261254 243 bytes

s=>{v=Array(w=32);p=526;b=n=>v[n>>5]&(1<<(n&31));B=(n,i)=>b(p+n)|b(p-n)?i:0;[...0+s].map(c=>v[(p+=[0,1,-1,w,-w]['0><v^'.indexOf(c)])>>5]|=1<<(p&31));for(z='',p=0;p<w*w;z+=' |-+'[b(p)?0:B(1,1)|B(w,2)||B(31,3)|B(33,3)],p++%w||(z+=
));return z}


### JSFiddle

• You can remove the return by replacing the ; with , and the {} with () Sep 19, 2016 at 20:33
• @Cyoce - There's a for loop in there which cannot be embedded that way. Sep 20, 2016 at 12:44
• then replace the { with eval(" and } with ") to remove the return codegolf.stackexchange.com/a/80967/41042 Sep 20, 2016 at 14:59
• @Cyoce - Unfortunately, I think I'd need to escape the literal linebreak as '\\n' if I do so. If I count correctly, that actually leads to +1 byte. Or is there a better way to embed the linebreak in the eval? Sep 20, 2016 at 15:36
• You would only need \n since template strings support literal new lines, but that would still leave it at the same byte count. Oh well Sep 20, 2016 at 19:40

# C, 246 bytes

n,y,*g,*p;main(c,v)char**v;{for(n=c*2+3,g=calloc(n*n,8),p=g+(n+1)*(c+1);c--;y=*v[c],p-=(y>70?n:1)*(y%5%4?-1:1))*p=1;for(y=n-1;--y;)for(c=n-1;c--;putchar(c?" |-++|-+"[*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4]:10))p=g+y*n+c;}


Takes input as separate characters, for example:

./mapper '>' '>' '>' 'v' 'v' 'v' '<' '<' '<' '^' '^' '^'


Or more conveniently, this (intentionally unquoted!) format:

./mapper $(echo '>>>vvv<<<^^^' | fold -w1)  Or for (pretty inefficient) random input: ./mapper$(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 10 | fold -w1)


And finally, using awk to crop the result means we can get much bigger:

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 500 | fold -w1) | awk '/[^ ]/{l=match($0,"\\+");if(l&&(l<L||!L))L=l;v[i++]=$0}END{for(;j<i;){l=v[j++];print substr(l,L,match(l," *$")-L)}}'


 +-----+
|     |
|     +-+  +-----+
|       |+-+     |
++       +|      ++
|         |      |
|         +      +-+
+--+               |
+-+               +--+
|     ++             |
+-+  +-++           +-+
++   |+--+          |
+-+ | |        ++  |
++ | ++   + +--+ ++
|  |  +---|      |
|  |     ++  +---+
++ |-+   |   |
| | +--+-+  |
| +    +    |
|        +--+
+--------+


Outputs to stdout. Uses the fact that padding is allowed around the map (produces a map which has edge length 2*n+1, putting the final position in the middle).

### Breakdown

This works by looping over the arguments in reverse and moving in reverse. It actually uses the fact that arg 0 is the program name; it doesn't matter what the name is, but it allows us to visit both the initial and last cell (as well as all cells in-between) without needing special handling.

n,                                  // Size of internal grid
y,                                  // Loop counter / current character
*g,                                 // Internal grid memory
*p;                                 // Current working pointer
main(c,v)char**v;{                  // K&R style function declaration
for(                            // Step 1: identify visited cells
n=c*2+3,                    //  Set output grid size
g=calloc(n*n,8),            //  Allocate map storage space
p=g+(n+1)*(c+1);            //  Start at centre
c--;                        //  Loop over directions in reverse
y=*v[c],                    //  Get current direction
p-=(y>70?n:1)*(y%5%4?-1:1)  //  Move in reverse
)*p=1;                          //  Mark cell visited
for(y=n-1;--y;)                 // For each row (except edges)
for(c=n-1;c--;              //   For each column (except edges, +1 for \n)
putchar(c?" |-++|-+"[   //   Print wall using lookup table
*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4
]:10)                   //   Or newline
)p=g+y*n+c;                 //   Set current cell (happens first)
}

• 236 bytes Jul 27, 2020 at 21:38