# 4-way intersection generator

Here is an ASCII-art of a 4-way intersection:

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


(Note how the horizontal roads are 3 rows tall, while the vertical roads are 5 columns wide. This is for aesthetic reasons, because of the rectangular font.)

Your challenge is to produce this ASCII art. However, as I'm sure you all know, not every intersection has a road travelling off in every single direction. This particular intersection goes NESW, but some intersections might go, for example, NW:

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


Or it might go SWE:

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


Or it may even go E, just a single direction (although you can hardly call this an intersection, but try to avoid being overly pedantic):

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


You need to write a program or function that can easily generate any of these combinations. More specifically, your challenge is to write a program or function that takes a string of directions, consisting of NESW, as input, and outputs or returns this ASCII art of an intersection with roads pointing in those directions. These directions may appear in any order, but the input will not contain any characters except for N, E, S, or W. If you like, you may request inputs to be lowercase instead, but you must specify this in your answer. You may also assume that all inputs will contain at least one direction.

The last example had leading spaces on each line, because there is no road going west. If you do not have a road going west, these leading spaces are optional. This:

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


Would also be an acceptable output. Similarly, if N or S is gone, empty lines in there place are optional. One trailing newline is allowed, and trailing spaces are allowed as long as the output is visually the same.

You may take input and output in any reasonable format, such as STDIN/STDOUT, command line args, files, function arguments/return values, etc.

As usual, this is , so try to get the shortest possible answer in whatever language you happen to use!

# Sample IO:

NESW:

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

NS:

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

S:

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

EW:

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

SE:
+-----+-----
|     |
|     |- - -
|     |
+-----+-----
|  |  |
|     |
|  |  |
|     |
|  |  |

• Are trailing spaces also allowed (if there's no E, for instance)? Are leading and trailing blank lines allowed if there's no N or S? Sep 6 '16 at 17:42
• @GregMartin Yes, those are allowed. See my edit. Sep 6 '16 at 17:46
• vaguely related, you reminded me of this code I mostly wrote, for road intersections in a roguelike game: github.com/CleverRaven/Cataclysm-DDA/blob/master/src/… Sep 6 '16 at 22:58

## Javascript (ES6), 190187 185 bytes

This is an attempt to build this ASCII art character per character by iterating on a 17x15 matrix. Therefore, the output is always made of 15 rows of 17 columns with the intersection of the roads centered in the middle.

p=>eval("for(y=15,s='';y--;s+=\n)for(x=17;x--;)s+=' |-+'[+[a=y>4,b=y<10,c=x>4,d=x<12].every((c,i)=>c|p.search('SNEW'[i])+1)&&!((z=x-8||y&1|a&b)&&z*z-9)+2*!((z=y-7||x&1|c&d)&&z*z-4)]")


### Ungolfed and commented

for(y = 15, s = ''; y--; s += \n)   // iterate on y, from 14 to 0 / append line feeds
for(x = 17; x--;)                   // iterate on x, from 16 to 0
s += ' |-+' [                     // append next character to string
+[ a = y > 4,                   // a = outside South area?
b = y < 10,                  // b = outside North area?
c = x > 4,                   // c = outside East area?
d = x < 12 ]                 // d = outside West area?
.every((c, i) =>                // for each area, see if either:
c |                           //   - we're currently outside it
p.search('SNEW' [i]) + 1      //   - or it's an allowed area (p = function param.)
)                               // if all tests pass, add a:
&&                              //   - vertical bar (encoded as 1) if:
!((z = x - 8 || y & 1 | a & b)  //     - x=8, y is even and we're not in the middle
&& z * z - 9)                   //     - OR x=5 OR x=11 (<=> (x-8)*(x-8) = 9)
+ 2 *                           //   - horizontal bar (encoded as 2) if:
!((z = y - 7 || x & 1 | c & d)  //     - y=7, x is even and we're not in the middle
&& z * z - 4)                   //     - OR y=5 OR y=9 (<=> (y-7)*(y-7) = 4)
]                                 // (vertical + horizontal = 3, which leads to '+')


### Matrix

Below is the matrix with the coordinates used in the code.

### Demo

The following snippet allows to try any road configuration.

let f =
p=>eval("for(y=15,s='';y--;s+=\n)for(x=17;x--;)s+=' |-+'[+[a=y>4,b=y<10,c=x>4,d=x<12].every((c,i)=>c|p.search('SNEW'[i])+1)&&!((z=x-8||y&1|a&b)&&z*z-9)+2*!((z=y-7||x&1|c&d)&&z*z-4)]")

function update() {
document.getElementById("o").innerHTML = f(document.getElementById("s").value);
}
update();
<input id="s" size=4 value="NSEW" oninput="update()">
<pre id="o" style="font-size:9px"></pre>

## PowerShell v3+, 226204192 191 bytes

param([char[]]$a)($n=0..4|%{($x=' '*5*($b=87-in$a))+('| | |',($w='|     |'))[$_%2]})*(78-in$a)
($z=($y='-'*5)*$b+"+$y+"+$y*($c=69-in$a))$x+$w '- - -'*$b+$w+'- - -'*$c
$x+$w
$z$n*(83-in$a)  Takes input as a string of capital letters, explicitly casts it as a char array. Constructs the "North" segment via looping from 0 to 4. Each loop, constructs a string of 5 spaces (if W/87 is present in the input), stores that in $x, then either | | (stored in $w) or | | |, depending upon whether we're currently even or odd. That array of strings is stored into $n, and multiplied by whether N/78 is -in the input. That will determine if $n is placed on the pipeline or not. Then, we construct the middle portion. The first line, $z is the "top" of the east-west route, using the same logic for W and E/69, and surrounded in parens to also place a copy on the pipeline. We use helper variable $y to save a byte on the ----- sections. The next line is just the appropriate number of spaces (i.e., $x) string-concatenated with the correct-width pipes (i.e., $w). Then, the middle striped line, again with W and E logic and $w filling in the middle. Then $x+$w and $z again. Finally, since the South road is the same as the north, put $n on the pipeline if S/83 is -in $a. All of those resultant strings are gathered from the pipeline and output is implicit at the end of program execution. Abuses the default Write-Output delimiter to insert a newline between elements. ### Examples PS C:\Tools\Scripts\golfing> .\4-way-intersection.ps1 'EN' | | | | | | | | | | | | | +-----+----- | | | |- - - | | +-----+----- PS C:\Tools\Scripts\golfing> .\4-way-intersection.ps1 'SNW' | | | | | | | | | | | | | -----+-----+ | | - - -| | | | -----+-----+ | | | | | | | | | | | | | PS C:\Tools\Scripts\golfing> .\4-way-intersection.ps1 'WE' -----+-----+----- | | - - -| |- - - | | -----+-----+-----  # C++ 317280 276 bytes int i(char*j){for(int y=0;y<15;++y)for(int x=0;x<18;++x)putchar(x-17?y<5&!strchr(j,'N')|y>9&!strchr(j,'S')|x<5&!strchr(j,'W')|x>11&!strchr(j,'E')?' ' :x==5|x==11?y==5|y==9?'+':'|':y==5|y==9?x==5|x==11?'+':'-':x==8&y%2|y==7&x%2?' ':x==8&(y/5-1)?'|':y==7&(x/6-1)?'-':' ':'\n');}  Ungolfed: int i (char* j) { for (int y=0; y<15; ++y) for (int x=0; x<18; ++x) putchar( x-17 ? y<5 & !strchr(j,'N') | y>9 & !strchr(j,'S') | x<5 & !strchr(j,'W') | x>11 & !strchr(j,'E') ? ' ' : x==5 | x==11 ? y==5 | y==9 ? '+' : '|' : y==5 | y==9 ? x==5 | x==11 ? '+' : '-' : x==8 & y%2 | y==7 & x%2 ? ' ' : x==8 & (y / 5 - 1) ? '|' : y==7 & (x / 6 - 1) ? '-' : ' ' : '\n'); }  • Holy nested ternary operators, Batman! – user18932 Sep 7 '16 at 0:37 • We always knew they'd be good for something. Sep 7 '16 at 4:26 • Replacing strchr with index will shave off few more. Define x and y together outside for loops. Mar 11 '17 at 18:13 # Python 3, 186 bytes S=' -- - -- - --' lambda d:'\n'.join(S[r//4:15*('W'in d):3]+'||+ - -| - - -||+'[r%4::3]+S[r//4:15*('E'in d):3]for r in[0,1,0,1,0,6,1,9,1,6,0,1,0,1,0][5-5*('N'in d):10+5*('S'in d)])  An anonymous lambda called with a string of directions, e.g. 'NWS' ### Explanation to follow # sed 234 s,$,@+-----+@|     |@!     !@|     |@+-----+@,
:l;tl
/N/s,^,#,;t
:r
/S/s,@\$,#,;t
/E/{s,!@,|- - -@,;s,+@,+-----@,g}
/W/{s,@!,@- - -|,;s,@+,@-----+,g;s,@|,@     |,g}
y,@!NSEW,\n|    ,
q
:
s,#,@|  |  |@|     |@|  |  |@|     |@|  |  |,
tr


It just builds the different parts if the proper character is on the line.
Uses @ instead of \n and subs \n back in at the end.
The north and south parts are identical, so I use what's basically a function to insert them.

## Batch, 351344 341 bytes

@echo off
set/pi=
set t=
if not "%i:n=%"=="%i%" call:l
set l=-----
set r=%l%
if "%i:w=%"=="%i%" set l=%t%
if "%i:e=%"=="%i%" set r=
for %%s in (%l%+-----+%r% "%t%|%t%|" "%l:--=- %|%t%|%r:--=- %" "%t%|%t%|" %l%+-----+%r%) do echo %%~s
if "%i:s=%"=="%i%" exit/b
:l
call :m
call :n
:n
echo %t%^|%t%^|
:m
echo %t%^|  ^|  ^|


Note: The line set t= ends in five spaces, and the line if "%i:e=%"=="%i%" set r= ends in a space. Takes case-insensitive input from STDIN. Edit: Saved 7 bytes by eliminating the d variable. Saved 3 bytes by using a for loop to print the middle section. If I'm allowed separate command-line parameters instead, then for 326 319 316 bytes:

@echo off
set t=%*
set/an=s=e=w=5,%t: ==%=0
set t=
call:%n%
set r=-----%t%
call set l=%%r:~%w%,5%%
call set r=%%r:~%e%%%
for %%s in (%l%+-----+%r% "%t%|%t%|" "%l:--=- %|%t%|%r:--=- %" "%t%|%t%|" %l%+-----+%r%) do echo %%~s
goto %s%
:0
call :1
call :2
:2
echo %t%^|%t%^|
:1
echo %t%^|  ^|  ^|
:5


## Python 2, 290 bytes

t,s,r,i=[],[],range(5),raw_input()
for n in r:t+=[" "*5*("W"in i)+"|  "+("|"," ")[n%2]+"  |"]
exec"s+=['-'*5];s[:1]+=' '*5,;"*2;s[:2]+="- - -",
if"N"in i:print'\n'.join(t)
print'\n'.join([s[n]*("W"in i)+("|     |","+-----+")[nin"04"]+s[n]*("E"in i)for n in r])
if"S"in i:print'\n'.join(t)

• m,t,s=[],[],[] could be m=t=s=[]. Sep 7 '16 at 6:13
• range(5) could be saved into a variable and used twice, instead of typing range(5) twice. Sep 7 '16 at 6:15
• What is m for? Sep 7 '16 at 14:18
• @TuukkaX, for some reason having t=s=[] messes everything up Sep 7 '16 at 14:37
• I'm now certain that by doing m=t=s=[], they all point to the same reference. Sep 8 '16 at 3:54

# GolfScript, 154 bytes

{a?1+}:x;'-'5*:e;' '5*:b;"+"e+"+"+:f;{b'|'b'|'b n}:k;{'W'x{e}{b}if\'E'x{e}{}if n}:y;{x{b"|  |  |
"+:c k c k c}{}if}:z;1/:a;'N'z f y k'|'b+'|'+ y k f y'S'z


Try it online!

• Impressive, no idea how this has no votes. Sep 12 '16 at 23:14

# Pyth (385380373 353 bytes)

Golfed:

K"     |  |  |\n     |     |\n"?}\Nz++KKPKk?}\Wz?}\Ez+++*5\-*2+\+*5\-"\n     |     |\n- - -|     |- - -\n     |     |\n"+*5\-*2+\+*5\-++*2+*5\-\+"\n     |     |\n- - -|     |\n     |     |\n"*2+*5\-\+?}\Ez+"     "+*2+\+*5\-"\n     |     |\n     |     |- - -\n     |     |\n     +-----+-----"++"     +-----+\n"*3"     |     |\n""     +-----+"?}\Sz++KKPKk


Ungolfed:

K"     |  |  |\n     |     |\n"  //sets K to first two lines of north
?}\Nz                            //if north in the input
++KKPK                         //then: return K + K + K[:-1]
k                              //else: return ""
?}\Wz                            //if West in input
?}\Ez                          //if East in input
+++*5\-*2+\+*5\-"\n     |     |\n- - -|     |- - -\n     |     |\n"+*5\-*2+\+*5\-    //then: Return E+W string
++*2+*5\-\+"\n     |     |\n- - -|     |\n     |     |\n"*2+*5\-\+         //else: Return W string
?}\Ez                          //else: if east in input (and not W)
+"     "+*2+\+*5\-"\n     |     |\n     |     |- - -\n     |     |\n     +-----+-----" //return East without West String
++"     +-----+\n"*3"     |     |\n""     +-----+" \\Return empty left and right intersection
?}\Sz                            //if south in input
++KKPK                         //return north string
k                              //return ""


Of course, if there are any improvements please tell me.

Saved 5 bytes thanks to Maltysen

You can try it here

• you can use K instead of N and then when assigning for the first time, you don't have to use an =, saving you a byte Sep 12 '16 at 1:15
• also, N[:-1] is P Sep 12 '16 at 1:17

# Groovy (274 Bytes)

## Ungolfed

r{
l->
t='+-----+'
s='     ';
m='|     |'
x='-----'
v=(1..5).collect{s}
nsR=(1..5).collect{[s,((it%2)?'|  |  |':m),s]}
ewR=[x,s,'- - -',s,x]
c=[l[3]?ewR:v,[t,m,m,m,t],l[1]?ewR:v]
(l[0]?nsR.collect{it}:[])+((0..4).collect{x->((0..2).collect{y->c[y][x]})}​)​+​(l[2]?nsR.collect{it}:[])
}


## Golfed

def i(l) {t='+-----+';s='     ';m='|     |';x='-----';v=(1..5).collect{s};n=(1..5).collect{[s,((it%2)?'|  |  |':m),s]};e=[x,s,'- - -',s,x];c=[l[3]?e:v,[t,m,m,m,t],l[1]?e:v];(l[0]?n.collect{it}:[])+((0..4).collect{x->((0..2).collect{y->c[y][x]})}​)​+​(l[2]?n.collect{it}:[])}