[Question]
  [
### Introduction
"Yarr!! We had a laddie who called himself a "programmer" make a map t' our hidden treasure! But 'tis written wit' weird numbers 'n letters! "E5, N2, E3"... what does it even mean? Madness! Can't even scribe a proper treasure map, t' useless cretin. Fix it fer us! We'll gift ye a share o' t' treasure!"
### Challenge Description
A group of pirates are having trouble reading a treasure map. Can you write a program to convert it into a more... piratey form?
As input, you'll receive the original treasure map. It's a list of comma separated strings, each string which consists of a *letter portion* (which tells the pirates which direction they need to walk in), and a *number portion* (which tells the pirates how many steps to take in that direction). For instance, the following treasure map:
```
E2,N4,E5,S2,W1,S3
```
would mean, "walk two steps to the east, walk four steps to the north, walk five steps to the east, walk two steps to the south, walk one step to the west, then walk three steps to the south."
As output, you'll output the map in a graphical form, using the characters `>`, `^`, `v`, and `<` as pointers. Here's the output for the above input:
```
  >>>>>v
  ^    v
  ^   v<
  ^   v
>>^   X
```
Notice that we've replaced the last step to the south with an `X` instead. This is because the last step is where the treasure is, and as we all know, pirates must have an X on their treasure maps, otherwise they won't know how to read it. 
By the way, the map won't ever cross itself, so you don't need to worry about dealing with overlaps. Also, you are allowed to have a trailing new line at the end of the output.
### Sample Inputs and Outputs
```
S5,W2
```
```
 v
 v
 v
 v
 v
X<
```
```
N1,E1,S1,E1,N1,E1,S2
```
```
>v>v
^>^X
```
```
N1
```
```
X
```
```
N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2
```
```
>>>>>>v
^>>>>vv
^^>>vvv
^^^Xvvv
^^^^<vv
^^^<<<v
^^<<<<<
```
```
E21,S2
```
```
>>>>>>>>>>>>>>>>>>>>>v
                     X
```
```
N12,E11,S12,W2,N4
```
```
>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
```
  
[Answer]
# Python 2, ~~249~~ ~~248~~ ~~244~~ ~~239~~ 237 bytes
```
D={}
m=X=Y=0
for s in input().split(","):d=ord(s[0])%10%7;exec"a,b=X,Y;E=D[Y]=D.get(Y,{});E[X]='<^>v'[d];m=min(m,X);%c+=d-2|1;"%(88+d%2)*int(s[1:])
D[b][a]="X"
for Y in sorted(D):print"".join(D[Y].get(n," ")for n in range(m,max(D[Y])+1))
```
Input like `"E2,N4,E5,S2,W1,S3"`.
`NSEW` is mapped to `[1, 3, 2, 0]` by `d=ord(c)%10%7`. Whether to change `y` or `x` is then decided by `d%2`, and whether to increment or decrement is decided by `d-2|1`. The first and third expressions were found by brute force.
Other than that, it's a simple usage of a nested dictionary of the form `{y: {x: char}}`.
*(Thanks to @joriki for help with mapping)*
[Answer]
# Javascript (ES6), 260
This was an interesting one...
Thanks @ETHproductions, @edc65, and @vihan for the help!
```
s=>{z=o=""
m=[]
q=x=y=2e3
s.split`,`.map(v=>z+=v[0].repeat(+v.slice(1)))
for(i=0;d=z[i];q=x<q?x:q)(m[y]=m[y]||[])[x]=z[++i]?d=="N"&&--y?"^":d=="S"&&++y?"v":d=="W"&&--x?"<":++x?">":o:"X"
m.map(a=>a.map((b,j)=>o+=" ".repeat(-p-1+(p=j))+b,p=q-1,o+=`
`))
return o}
```
This defines an anonymous function, so to call it add `f=` to the beginning to give it a name.
To test: `console.log(f("E2,N4,E5,S2,W1,S3"))`
### Explanation:
```
s=>{ //define function w/ parameter s
z=o=""      //z=modified input, o=final output
m=[]        //map of characters
q=x=y=2e3   //q=minimum value of x; x+y=coordinates. These start high to leave room to go backwards
s.split`,`.map(v=>z+=v[0].repeat(+v.slice(1)))    //change "N3,E4" -> "NNNEEEE", and put in z
for(i=0;d=z[i];q=x<q?x:q)   //for each direction d in z, while updating q:
    (m[y]=m[y]||[])[x]=     //in the right place on the map, put:
        z[++i]?                 //if last character of z, "X"
            d=="N"&&--y?"^":    
            d=="S"&&++y?"v":    //otherwise get the right character and change x+y accordingly
            d=="W"&&--x?"<":
            ++x?">":o
        :"X"
m.map(a=>a.map((b,j)=>o+=" ".repeat(-p-1+(p=j))+b,p=q-1,o+=`
`)) //dump map to o, with correct padding
return o}   //return
```
[Answer]
# Ruby, ~~213 209 198 186~~ 178
```
M={};x=0,m=q=0
gets.scan(/.(\d+)/){?1.upto($1){m,y=x
x[d=$&.ord%10%7-2]+=1|($u=M[y]||={})[m]=d
m<q&&q=m}}
$u[m]=2
puts M.sort.map{|_,b|(q..b.max[0]).map{|k|">vX <^"[b[k]||3]}*""}
```
Pass input via stdin.
This uses a `y -> x -> char` dictionary to construct the map, where both `x` and `y` can be negative. Once the input has been parsed, the global minimum of the x coordinate is extracted. For each row, it then iterates over a range going from the global minimum to the maximum index for the current line, and prints the correct character for that index.
To stay with the theme, the expressions to turn `NESW` into the proper indices were shamelessly pirated from [Sp3000](https://codegolf.stackexchange.com/users/21487/sp3000)'s [answer](https://codegolf.stackexchange.com/a/54308/84).
Original version that used a `[x,y] -> char` dictionary:
```
M={};x=0,0
gets.scan(/.(\d+)/){(?1..$1).map{x[d=$&.ord%10%7-2]+=1|M[$y=x+[]]=d}}
M[$y]=2
a,*q=M.minmax.flatten
M.map{|(x,y),v|($*[y-M.map{|a,|a[1]}.min]||=?\s.*q[2]-a)[x-a]=">vX<^"[v]}
puts$*.map &:rstrip
```
[Answer]
# PHP, ~~431~~ 417 bytes
```
$g=explode(',',$argv[1]);$x=$y=$a=$b=$c=$d=$e=$f=0;
foreach($g as$i=>$h){list($k,$l,$m)=
    ['N'=>[-1,0,'^'],'E'=>[0,1,'>'],'S'=>[1,0,'v'],'W'=>[0,-1,'<']][$h[0]];
    for($s=substr($h,1);$s--;){$z[$f=$y][$e=$x]=$m;$y+=$k;$x+=$l;}
    if($i==count($g)-1){$x=$e;$y=$f;}
    $a=min($a,$x);$b=max($b,$x);$c=min($c,$y);$d=max($d,$y);
}$z[$y][$x]='X';for($y=$c;$y<=$d;$y++)
{$o='';for($x=$a;$x<=$b;$x++)$o.=$z[$y][$x]?:' ';echo rtrim($o)."\n";}
```
Put it into a file (`treasure.php`), remove the indentation, join the lines (it is wrapped here for readability), put the `<?php` marker at the beginning of the file (not displayed here as it is technically not a part of the program).
Example of execution:
```
$ php -d error_reporting=0 treasure.php E2,N4,E5,S2,W1,S3
  >>>>>v
  ^    v
  ^   v<
  ^   v
>>^   X
$
```
The option `-d error_reporting=0` is needed to suppress notices about values not found at specified indices in `$z`.
**Update:**
While I was preparing the [ungolfed version of the code](https://github.com/axiac/code-golf/blob/master/yarr-a-map-to-the-hidden-treasure.php) for posting I discovered it contained two unneeded assignments (12 bytes) and a whitespace that can be removed(`as$i`); also, by replacing a `while` with a `for` loop and squeezing an assignment into it (not possible using the `while` loop) I saved another byte.
[Answer]
# Perl, 702 613 546 474 439 338 260 bytes
Thanks to Dom Hastings for his help and his supergolfed version.  
The code uses a 2D array.
Version by Dom Hastings:
```
$x=$y=$a=$b=99;map{/^./;$a=($c=$x)<$a?$x:$a,$A=$x>$A?$x:$A,$b=($C=$y)<$b?$y:$b,$B=$y>$B?$y:$B,$q[$c][$C]={split'','W<E>N^Sv'}->{$&},$x+={W,-1,E,1}->{$&},$y+={N,-1,S,1}->{$&}for 1..$'}split',',pop;$q[$c][$C]=X;for$y($b..$B){print$q[$_][$y]||$"for$a..$A;print$/}
```
My lesser golfed version of 338 bytes (for reference):
```
@m=split(',',pop);$x=$y=$a=$b=99;map{($d,$s)=/^(.)(.+)$/;for(1..$s){$c=$x;$C=$y;if($x<$a){$a=$x}if($x>$A){$A=$x}if($y<$b){$b=$y}if($y>$B){$B=$y}if($d eq"W"){$r="<";$x--}if($d eq"E"){$r=">";$x++}if($d eq"N"){$r="^";$y--}if($d eq"S"){$r=v;$y++}$q[$c][$C]=$r}}@m;$q[$c][$C]=X;for$y($b..$B){for$x($a..$A){$t=$q[$x][$y];print$t?$t:$"}print$/}
```
Test
```
$ perl piratemap_golf.pl E4,N3,W6,S10,W1,S1,E5,N1,W2,N6,E6,N5,W10,S1,E2
v<<<<<<<<<<
>Xv<<<<<< ^
  v     ^ ^
  v     ^ ^
  v >>>>^ ^
  v >>>>>>^
  v ^
  v ^
  v ^
  v ^
  v ^
 v< ^<<
 >>>>>^
```
[Answer]
## Python 2, 394 bytes
Run the program then paste into standard input as e.g. `"E2,N4,E5,S2,W1,S3"`
```
m=input().split(',')
def f(x,y,h,o,s=[]):
 for c in m:
  for _ in range(int(c[1:])):
   a,b,l={'E':(1,0,'>'),'W':(-1,0,'<'),'N':(0,1,'^'),'S':(0,-1,'v')}[c[0]]
   if o:o[h-y][x]=l
   s+=[(x,y)];x+=a;y+=b
 if o:o[h-y+b][x-a]='X'
 return s
p,q=zip(*f(*[0]*4))
w,h=max(p)-min(p),max(q)-min(q)
o=[[' ']*-~w for _ in range(h+1)]
f(-min(p),-min(q),h,o)
print'\n'.join(["".join(l).rstrip()for l in o])
```
This is not very optimized. First it runs through the input to record the path. Then it does some math to determine the right starting position and size of `o`. Then it runs through again and sets the appropriate entries of `o` as one of `>v<^X`. The main cleverness is in reusing the same function for both these traversals.
[Answer]
# XQuery 3.0, 498
```
declare variable $v external;let $m:=<v>{tokenize($v,',')!(for $j in(1 to xs:int(substring(.,2)))return<c>{translate(substring(.,1,1),'NESW','^>v<')}</c>)}</v>/c!(let $p:=./preceding-sibling::c return<p x="{count($p[.='>'])-count($p[.='<'])}" y="{count($p[.='v'])-count($p[.='^'])}">{if(./following::*)then .else'X'}</p>)for $y in(min(xs:int($m/@y))to max(xs:int($m/@y)))return string-join(for $x in(min(xs:int($m/@x))to max(xs:int($m/@x)))let $d:=$m[@x=$x and @y=$y]return if($d)then$d else' ','')
```
XQuery isn't often even slightly competitive, so this was fun. 
## Ungolfed
```
declare variable $v external;
let $map := <vector>{ tokenize($v,',') ! 
        (for $j in (1 to xs:int(substring(.,2)))
            return <step>{ translate(substring(.,1,1),'NESW','^>v<') }</step> ) 
         }</vector>/step !
            (let $path_so_far := ./preceding-sibling::step
            return <point 
                x="{ count($path_so_far[.='>']) - count($path_so_far[.='<']) }" 
                y="{ count($path_so_far[.='v']) - count($path_so_far[.='^']) }">
                {if(./following::*) then string(.) else 'X'}
            </point>)
for $y in (min(xs:int($map/@y)) to max(xs:int($map/@y)))
return string-join(
    for $x in (min(xs:int($map/@x)) to max(xs:int($map/@x)))
    let $d := $map[@x=$x and @y=$y]
    return if($d) then string($d) else ' '
    ,'')
```
[Answer]
# PHP, 496 ~~514~~ ~~528~~
I tried my luck in PHP, the result is rather long, I still want to post it, just for fun.
```
function a($c){global$a,$b;$a[$b[1]][$b[0]]=$c;}$c=explode(',',$argv[1]);$a=[];$b=[0,0];foreach($c as$d=>$e){$f=substr($e,1);if($d==count($c)-1)$f--;for($i=0;$i++<$f;){if($e[0]==N){a('^');$b[1]--;}elseif($e[0]==E){a('>');$b[0]++;}elseif($e[0]==S){a(v);$b[1]++;}else{a('<');$b[0]--;}}}a(X);$d=$e=$f=$g=0;foreach($a as$y=>$h){$f=min($f,$y);$g=max($g,$y);foreach($h as$x=>$i){$d=min($d,$x);$e=max($e,$x);}}for($y=$f;$y<=$g;$y++){for($x=$d;$x<=$e;$x++)echo isset($a[$y][$x])?$a[$y][$x]:' ';echo "
";}
```
## Ungolfed
```
<?php
    function setInMap($char) {
        global $map, $position;
        $map[$position[1]][$position[0]] = $char;
    }
    $instructions = explode(',', $argv[1]);
    $map = [];
    $position = [0, 0];
    foreach($instructions as $index => $instruction) {
        $count = substr($instruction, 1);
        if($index === count($instructions) - 1) {
            $count--;
        }
        for($i = 0; $i < $count; $i++) {
            if($instruction[0] === 'N') {
                setInMap('^');
                $position[1]--;
            } elseif($instruction[0] === 'E') {
                setInMap('>');
                $position[0]++;
            } elseif($instruction[0] === 'S') {
                setInMap('v');
                $position[1]++;
            } else($instruction[0] === 'W') {
                setInMap('<');
                $position[0]--;
            }
        }
    }
    setInMap('X');
    $minX = $maxX = $minY = $maxY = 0;
    foreach($map as $y => $row) {
        $minY = min($minY, $y);
        $maxY = max($maxY, $y);
        foreach($row as $x => $cell) {
            $minX = min($minX, $x);
            $maxX = max($maxX, $x);
        }
    }
    for($y = $minY; $y <= $maxY; $y++) {
        for($x = $minX; $x <= $maxX; $x++) {
            if(isset($map[$y][$x])) {
                echo $map[$y][$x];
            } else {
                echo ' ';
            }
        }
        echo "\n";
    }
?>
```
[Answer]
# JavaScript (ES6), 244 ~~249 274~~
Leading spaces and newlines added for clarity and not counted, **except** the newline near the end in the join call, that is significant and counted.
Test running the snippet (being ECMAScript 6, Firefox and Safari 9 only)
```
F=m=>(
  x=y=0,p=[],
  m.replace(/\w(\d+)/g,(d,z)=>{
    for(d='NWSE'.search(d[0]);
        z--&&(p=~x?~y?p:[y=0,...p]:p.map(r=>' '+r,x=0));
        p[u=y]=(w=r.slice(0,x))+'^<v>'[d]+(v=r.slice(x+1)),
        d&1?x+=d-2:y+=d-1)
      for(r=p[y]||'';!r[x];)r+=' ';
  }),
  p[u]=w+'X'+v,
  p.join`
`
)
// TEST
out=x=>O.innerHTML+=x.replace(/</g,'&lt;')+'\n'
;['S5,W2','N1,E1,S1,E1,N1,E1,S2','N1','N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2','E21,S2','N12,E11,S12,W2,N4']
.forEach(a=>out(a+'\n'+F(a)+'\n'))
```
```
<pre id=O></pre>
```
[Answer]
# C, 557
```
main(_,a,minX,maxX,minY,maxY,x,y,v,dir,dist)char**a;char*v;{char o[998][999];for(y=0;y-998;++y){for(x=0;x-998;++x)o[y][x]=32;o[y][998]=0;}y=x=minY=minX=maxY=maxX=499;v=a[1];while(*v){dir=*v++;dist=atoi(v);while(*v&&*v!=44)v++;v+=!!*v;if(dir==78){while(dist--)o[y--][x]=94;if(y<minY)minY=y;y+=!*v;}if(dir==69){while(dist--)o[y][x++]=62;if(x>maxX)maxX=x;x-=!*v;}if(dir==83){while(dist--)o[y++][x]=86;if(y>maxY)maxY=y;y-=!*v;}if(dir==87){while(dist--)o[y][x--]=60;if(x<minX)minX=x;x+=!*v;}}o[y][x]=88;for(y=minY;y<=maxY;++y){o[y][maxX+1]=0;puts(o[y]+minX);}}
```
Ungolfed version:
```
#include <stdio.h>
#define MAX_WIDTH 998
#define MAX_HEIGHT 998
int main(int argc, char *argv[]) {
    int minX,maxX,minY,maxY;
    int x,y;
    char output[MAX_HEIGHT][MAX_WIDTH+1];
    char *v;
    
    for (y=0; y<MAX_HEIGHT; ++y) {
        for (x=0; x<MAX_WIDTH; ++x) 
            output[y][x] = ' ';
        output[y][MAX_WIDTH] = 0;
    }
    x = minX = maxX = MAX_WIDTH/2;
    y = minY = maxY = MAX_HEIGHT/2;
    v = argv[1];
    while (*v) {
        char dir; int dist;
        dir = *(v++);
        dist = atoi(v);
        while (*v && *v != ',') v++;
        if (*v) v++;
        switch (dir) {
            case 'N':case 'n':
                while (dist--) output[y--][x] = '^';
                if (y < minY) minY = y;
                if (!*v) y++;
                break;
            case 'E':case 'e':
                while (dist--) output[y][x++] = '>';
                if (x > maxX) maxX = x;
                if (!*v) x--;
                break;
            case 'S':case 's':
                while (dist--) output[y++][x] = 'v';
                if (y > maxY) maxY = y;
                if (!*v) y--;
                break;
            case 'W':case 'w':
                while (dist--) output[y][x--] = '<';
                if (x < minX) minX = x;
                if (!*v) x++;
                break;
        }
    }
    output[y][x] = 'x';
    for (y = minY; y <= maxY; ++y) {
        output[y][maxX+1] = 0;
        puts(output[y]+minX);
    }
    return 0;
}
```
Dynamic memory allocation isn't much harder, but malloc is far too long an identifier to be used in code golf. I feel like there should be some kind of PCG.h header legally auto-included for golfing in c, just to shorted some identifiers.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~61~~ 60 bytes
```
‚ÄúESWN‚Äùi‚±Æo)¬µ·ªã√ò.,U;N$¬§W·∫ã…ó/‚Ç¨·∫é·∏£1;∆ä+\·πñZ·πÇ‚Ç¨·∫°∆ä‚Äò≈í·π¨‚Ç¨a"≈í·πô-0¬¶$S·ªã‚Äú>v<^X ‚Äù
```
[Try it online!](https://tio.run/##y0rNyan8//9RwxzX4HC/Rw1zMx9tXJeveWjrw93dh2fo6YRa@6kcWhL@cFf3yen6j5rWPNzV93DHYkPrY13aMQ93Tot6uLMJLLrwWNejhhlHJz3cuQbIT1QCsWbqGhxaphIMNAlovF2ZTVyEAtCC/w93LgZSOg93LLIOA@pqWnO4PZLLGqhEIT2zLLVYITex4NA2oArrw@1cD3dvOdwOVJL1qHHfoW2Htv3/H2yqE27E5Weo42qoEwwmoWyQIJefmY6rmU6wmU64qY6fqY6riU6wiU64sY6fsY6rEVCNTjhQvRGXqxFUgxFQK8gcoISRjp8JAA "Jelly ‚Äì Try It Online")
A monadic link taking as its argument the directions as a list of lists, each of which has the compass direction character as its first member and the number of moves as an integer as its second. Returns a list of Jelly strings representing the map.
[Answer]
# Groovy, 359
```
c=args[0].split(',').collect{[it[0],it[1..-1]as int]}
m=[[]]
x=y=0
d=["N":["^",0,1],"S":["v",0,-1],"E":[">",1,0],"W":["<",-1,0]]
c.each{z->(1..z[1]).each{if(x<0){m*.add(0," ");x=0};if(y<0){m.add(0,[]);y=0};m[y]=m[y]?:[];m[y][x]=d[z[0]][0];if(c.last()==z&&it==z[1])m[y][x]='X';y+=d[z[0]][2];x+=d[z[0]][1]}}
m.reverse().each{println it.collect{it?:" "}.join()}
```
[Answer]
# Common Lisp - 603
```
(lambda(s)(do((x 0)i(y 0)j(p 0)r(q 0)(g(mapcar(lambda(x)`(,(aref x 0),(parse-integer x :start 1)))(split-sequence:split-sequence #\, s))(cdr g))c)((not g)(setf x 0 y 0)(dolist(e(stable-sort(sort r #'<= :key #'car)#'< :key #'cadr))(dotimes(_(-(cadr e)p y))(terpri)(incf y)(setf x 0))(dotimes(_(-(car e)q x))(princ" ")(incf x))(princ(caddr e))(incf x)))(case(caar g)(#\N(setf i 0 j -1 c #\^))(#\E(setf i 1 j 0 c #\>))(#\W(setf i -1 j 0 c #\<))(#\S(setf i 0 j 1 c #\v)))(dotimes(_(-(cadar g)(if(cdr g)0 1)))(push`(,x,y,c)r)(incf x i)(incf y j))(setf q(min q x)p(min p y))(unless(cdr g)(push`(,x,y #\X)r))))
```
Array-free implementation: prints from top to bottom, from left to right.
* Parse and expands directions into a trace of `(x y char)` elements:
The simple "N3" input produces `((0 0 #\^) (0 -1 #\^) (0 -2 #\X))`
* Also, compute the minimal `x` and `y`
* Sort the resulting trace by `y` first and then by `x`
* Iterate over the sorted list while moving cursor
	1. Add newlines and spaces to move current cursor at right position
	2. When at position `x - minx`, `y - miny`, print the desired character
### Examples
```
(loop for input in  '("N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2" 
                      "N1,E1,S1,E1,N1,E1,S2" 
                      "N12,E11,S12,W2,N4")
      do (fresh-line)
         (terpri)
      (funcall *fun* input))
```
Result:
```
>>>>>>v
^>>>>vv
^^>>vvv
^^^Xvvv
^^^^<vv
^^^<<<v
^^<<<<<
>v>v
^>^X
>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
```
[Answer]
# CoffeeScript, ~~303~~  285 bytes
```
Y=(s)->o=[];t=l=x=y=0;q='';q+=s[0]for[1..s[1..]]for s in s.split ',';q=q[..-2];(i='NWSE'.search c;(o[y]?=[])[x]='^<v>'[i];j=(i&2)-1;x+=j*(i&1);y+=j*(!(i&1));y<t&&t=y;x<l&&l=x)for c in q;(o[y]?=[])[x]='X';((o[y][x]||' 'for x in[l...o[y].length]).join ''for y in[t...o.length]).join '\n'
```
```
<script src="http://coffeescript.org/extras/coffee-script.js"></script>
<script type="text/coffeescript">
Y=(s)->o=[];t=l=x=y=0;q='';q+=s[0]for[1..s[1..]]for s in s.split ',';q=q[..-2];(i='NWSE'.search c;(o[y]?=[])[x]='^<v>'[i];j=(i&2)-1;x+=j*(i&1);y+=j*(!(i&1));y<t&&t=y;x<l&&l=x)for c in q;(o[y]?=[])[x]='X';((o[y][x]||' 'for x in[l...o[y].length]).join ''for y in[t...o.length]).join '\n'
#------------------
document.write '<pre>'
z=[
  'E2,N4,E5,S2,W1,S3'
  'S5,W2'
  'N1,E1,S1,E1,N1,E1,S2'
  'N1'
  'N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2'
  'E21,S2'
  'N12,E11,S12,W2,N4'
]
for w in z
  document.write "\n\n#{w}\n"
  document.write Y(w).replace /</g,'&lt;'
  
</script>
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 32 bytes
```
Ôº∑Ôº≥¬´‚âî‚åïENW¬ßŒπ‚Å∞Œ∏‚ú≥‚äóŒ∏√ó¬ß>^<vŒ∏Œ£Œπ¬ªÔº≠‚ú≥‚Å∫‚äóŒ∏‚Å¥X
```
[Try it online!](https://tio.run/##bc3BasJAFIXhtecphlndS1OoMWajCIIpuHAoTCFdCZoMeiFOajJJC6XPPlVKd92f7z/V@dBV7aGJ8eMsjVO09e9DsKETfyJm9YXJuu/l5OlZfE26MKVO1Dpsfe0@SRL1xJyoKy8webmZQBvpXBWk9bRph2PjarreF69ycT39Ob3aL0d9d4myw4WE@Vb4xq4d3b@Fh4wZvwf6TXOMJkeRw@Yo5zBzFBlshnIGM0ORwqYopzAp4mMz/gA "Charcoal ‚Äì Try It Online")
Input taken as a multiline string.
Link is to verbose version of code.
Golfed from 43 bytes with [Neil's help.](https://chat.stackexchange.com/transcript/message/56410590#56410590)
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal/tree/version-2), 390 [bitsv2](https://github.com/Vyxal/Vyncode/blob/main/README.md), 48.75 bytes
```
‚åê‚åä‚Ä∫?«çf`NESW`kd‚àö:¬£ƒø:·πÖ¬•`^>v<`ƒøfW‚à©v«î·π´‚ÅΩ‚Äπ·∫áwJ:tt\X1"pwJ‚üë√∑√∏‚àß
```
[Try it Online!](https://vyxal.pythonanywhere.com/?v=2&c=1#WyI9IiwiIiwi4oyQ4oyK4oC6P8eNZmBORVNXYGtk4oiaOsKjxL864bmFwqVgXj52PGDEv2ZX4oipdseU4bmr4oG94oC54bqHd0o6dHRcXFgxXCJwd0rin5HDt8O44oinIiwiIiwiTjEyLEUxMSxTMTIsVzIsTjQiXQ==)
Bitstring:
```
000110000111010100000001000100000101011110110001100110111110111101111011001110011001001000011101100001111110011101110101110100100100110111110011000000010110101101110001011010011010000010011111100110010101010011010000110000010100000110001000100010100110010101010000110101110111100001000011001100000001110101110111000000101111101011000110101100100110111100111111000101110011110111110101001011
```
```
‚åê‚åä‚Ä∫?«çf`NESW`kd‚àö:¬£ƒø:·πÖ¬•`^>v<`ƒøfW‚à©v«î·π´‚ÅΩ‚Äπ·∫áwJ:tt\X1"pwJ‚üë√∑√∏‚àß¬≠‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å™‚Äè‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å£‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å°‚Å™‚Äè‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å§‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å§‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å£‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å£‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Å§‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å¢‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå¬≠
‚åê‚åä‚Ä∫                                                    # ‚Äé‚Å°split by comma, get number part, increment
   ?«çf                                                 # ‚Äé‚Å¢get directions and flatten
      `NESW`                                           # ‚Äé‚Å£Directions
            kd‚àö                                        # ‚Äé‚Å§"02468"
               :¬£                                      # ‚Äé‚Å¢‚Å°duplicate and push to register
                 ƒø                                     # ‚Äé‚Å¢‚Å¢transliterate directions to corresponding canvas numbers
                  :·πÖ¬•                                  # ‚Äé‚Å¢‚Å£duplicate, join by nothing, push register
                     `^>v<`ƒø                           # ‚Äé‚Å¢‚Å§Transliterate each direction to corresponding arrow text
                            fW‚à©                        # ‚Äé‚Å£‚Å°flatten, wrap the stack and transpose
                               v«î                      # ‚Äé‚Å£‚Å¢‚Äé‚Å£‚Å§rotate each sublist to order [text, length, direction] for canvas
                                 ·π´‚ÅΩ‚Äπ·∫áwJ                # ‚Äé‚Å£‚Å£decrement the middle of the last triplet 
                                       :tt             # ‚Äé‚Å£‚Å§get the very last direction
                                          \X1"         # ‚Äé‚Å§‚Å°["X", 1]
                                              pwJ      # ‚Äé‚Å§‚Å¢prepend it to the direction and put it back (Draws the X) 
                                                 ‚üë√∑√∏‚àß  # ‚Äé‚Å§‚Å£draw each triplet to the canvas
üíé
```
Created with the help of [Luminespire](https://vyxal.github.io/Luminespire).
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~37~~ 35 (or ~~42~~ 38) [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
**38 bytes:** Input as comma-separated string, as mentioned in the challenge description:
```
',¬°Œµƒá"NESW"skxs"^>v<"√®)}√∏R`ƒÅ¬§√ä+≈†Œõ1'X0Œõ
```
[Try it online.](https://tio.run/##yy9OTMpM/f9fXefQwnNbj7Qr@bkGhysVZ1cUK8XZldkoHV6hWXt4R1DCkcZDSw53aR9dcG62oXqEwbnZ///7GRrpuBoa6gQD6XAjHT8TAA)
**35 bytes:** Input as a list of pairs of direction-character and distant-integer, by removing the first three bytes `',¬°`:  
[Try it online.](https://tio.run/##yy9OTMpM/f//3NYj7Up@rsHhSsXZFcVKcXZlNkqHV2jWHt4RlHCk8dCSw13aRxecm22oHmFwbvb//9HRSn5KOoZGsTrRSq5AhiGIEQwTCVfSAdNAJSaxsQA)
**Explanation (of the strict I/O program):**
```
',¬°           '# Split the (implicit) input-string on commas
   Œµ           # Map over each string:
    ƒá          #  Extract its head; push distant and direction-char separately
     "NESW"sk  #  Get the 0-based index of the character in "NESW"
             x #  Double it (without popping)
     s         #  Swap so the index is at the top again
      "^>v<"√®  #  Convert the index to the correct output character
     )         #  Wrap all three values into a list
    }√∏         # After the map: zip/transpose the list of triplets; swapping rows/columns
      R        # Reverse the list of triplets
       `       # Pop and push all three lists separately to the stack
        ƒÅ      # Push a list in the range [1,length]
         ¬§     # Push its last item (without popping the list)
          √ä    # Check for each that it's NOT equal to this last item
           +   # Add the values at the same positions
               # (so 1 is added to all distances, except the last one)
        ≈†      # Triple-swap the three lists on the stack
         Œõ     # Canvas builtin with these three arguments
               # (which is output immediately)
1'X0Œõ         '# And another Canvas builtin with arguments 1,"X",0
               # (which is done on top of the other Canvas and also output)
```
The Canvas builtin `Œõ` takes three arguments:
1. Length(s): which are the modified distances (+1 for every distance except the last one, since the Canvas builtin draws with overlapping corners)
2. The characters we want to display
3. The directions to draw in, which is in this case is \$0\$=North; \$2\$=South; \$4\$=South; \$6\$=West.
For example: input `E2,N4,E5,S2,W1,S3` will for `',¬°Œµƒá"NESW"skxs"^>v<"√®)}√∏R`ƒÅ¬§√ä+≈†` result in the three lists:
1. Lengths: `[3,5,6,3,2,3]`
2. Characters: `[">","^",">","v","<","v"]`
3. Directions: `[2,0,2,4,6,4]`
And will print them as:
```
  >>>>>v
  ^    v
  ^   v<
  ^   v 
>>^   v 
```
After which the `1'X0Œõ` will overwrite the final `v` with `X`.
[See this 05AB1E tip of mine for an in-depth explanation of the Canvas builtin.](https://codegolf.stackexchange.com/a/175520/52210)
]