9
\$\begingroup\$

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.

\$\endgroup\$
14
  • 3
    \$\begingroup\$ 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. \$\endgroup\$ – feersum Sep 1 '16 at 16:55
  • 3
    \$\begingroup\$ 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. \$\endgroup\$ – El'endia Starman Sep 1 '16 at 16:57
  • 2
    \$\begingroup\$ Excellent. I'd still suggest being explicit about how the dungeon is constructed from the movements. \$\endgroup\$ – El'endia Starman Sep 1 '16 at 17:04
  • 1
    \$\begingroup\$ What do you mean by "display map"? Is returning the map from a function allowed? \$\endgroup\$ – Paul Schmitz Sep 1 '16 at 17:04
  • 3
    \$\begingroup\$ 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?) \$\endgroup\$ – Dave Sep 4 '16 at 10:41
3
\$\begingroup\$

Javascript (ES6), 261 254 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

\$\endgroup\$
5
  • \$\begingroup\$ You can remove the return by replacing the ; with , and the {} with () \$\endgroup\$ – Cyoce Sep 19 '16 at 20:33
  • \$\begingroup\$ @Cyoce - There's a for loop in there which cannot be embedded that way. \$\endgroup\$ – Arnauld Sep 20 '16 at 12:44
  • \$\begingroup\$ then replace the { with eval(" and } with ") to remove the return codegolf.stackexchange.com/a/80967/41042 \$\endgroup\$ – Cyoce Sep 20 '16 at 14:59
  • \$\begingroup\$ @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? \$\endgroup\$ – Arnauld Sep 20 '16 at 15:36
  • \$\begingroup\$ 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 \$\endgroup\$ – Cyoce Sep 20 '16 at 19:40
3
\$\begingroup\$

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)
}
\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.