# ASCII Art of the Day #3 - Chinese Shrines

In today's episode of AAOD, we are going to construct a Chinese Shrine of varying heights.

Consider the following examples for height (N) 1 to 6

N = 1:

       .
|
.   ]#[   .
\_______/
.    ]###[    .
\__]#.-.#[__/
|___| |___|
|___|_|___|
####/_\####
|___|
/_____\


N = 2:

         .
|
.   ]#[   .
\_______/
.    ]###[    .
\___________/
.     ]#####[     .
\___]#.---.#[___/
|__|_|   |_|__|
|__|_|___|_|__|
#####/___\#####
|_____|
/_______\


N = 3:

           .
|
.   ]#[   .
\_______/
.    ]###[    .
\___________/
.     ]#####[     .
\_______________/
.      ]#######[      .
\____]#.-----.#[____/
|__|__|     |__|__|
|__|__|_____|__|__|
######/_____\######
|_______|
/_________\


N = 4:

             .
|
.   ]#[   .
\_______/
.    ]###[    .
\___________/
.     ]#####[     .
\_______________/
.      ]#######[      .
\___________________/
.       ]#########[       .
\_____]##.-----.##[_____/
|__|__|_|     |_|__|__|
|__|__|_|_____|_|__|__|
########/_____\########
|_______|
/_________\


N = 5:

               .
|
.   ]#[   .
\_______/
.    ]###[    .
\___________/
.     ]#####[     .
\_______________/
.      ]#######[      .
\___________________/
.       ]#########[       .
\_______________________/
.        ]###########[        .
\______]###.-----.###[______/
|__|__|___|     |___|__|__|
|__|__|___|_____|___|__|__|
##########/_____\##########
|_______|
/_________\


N = 6:

                 .
|
.   ]#[   .
\_______/
.    ]###[    .
\___________/
.     ]#####[     .
\_______________/
.      ]#######[      .
\___________________/
.       ]#########[       .
\_______________________/
.        ]###########[        .
\___________________________/
.         ]#############[         .
\_______]####.-----.####[_______/
|__|__|__|__|     |__|__|__|__|
|__|__|__|__|_____|__|__|__|__|
############/_____\############
|_______|
/_________\


and so on.

# Construction Details

I am sure most of the details about the pattern are clear. Here are some finer details:

• The door at the bottom of the shrine can at minimum be of 1 _ width and at maximum be of 5 _ width.
• There will always be two . directly above the pillars around the door (two vertical |).
• The stairs start with the same width as the door and increase like show in the pattern
• The ]##..##[ blocks above each roof level increase in size of 2 from top to bottom.
• The \__...__/ roofs levels increase in size of 4 from top to bottom.
• The walls blocks around the door should at minimum contain 1 _ and at maximum, 3 _ between the two |. Priority goes to the outer wall blocks so that the one closest to the door gets a varying size for each level.
• The space between the . and the ] (or [) is filled by # in the roof just above the doors.

# Challenge Details

• Write a function or full program that reads a positive integer greater than 0 via STDIN/ARGV/function argument or closest equivalent and outputs (to STDOUT or closest equivalent) the Nth Chinese Shrine
• Trailing newline is optional.
• There should either be no trailing spaces or enough trailing spaces to pad the output in the minimum bounding rectangle.
• There should not be any leading spaces that are not part of the pattern.

# Leaderboard

The first post of the series generates a leaderboard.

To make sure that your answers show up, please start every answer with a headline, using the following Markdown template:

# Language Name, N bytes


where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

• The door width seems rather arbitrary to me - why is it 1 in the N=1 case? Why not 3 and have smaller side windows like in the N=2 case? – Matty May 22 '15 at 13:49
• Also, in the N=1 case, isn't the first rooftop too long (wide)? – Matty May 22 '15 at 13:58
• @Matty regarding door - if door was of width 3, then there would be no # beside the . to support the ] and [ above it. About the starting roof size - That is the roof size in each height's top roof. – Optimizer May 22 '15 at 14:00
• I was asking about the bottom most roof just above the windows. In all other cases it is the size of the roof above it +4 (+2 on either sides). But here it is +8. – Matty May 22 '15 at 14:18
• @Matty oh, you are right. Fixed. – Optimizer May 22 '15 at 14:21

# CJam, 200 bytes

-4'.-4'|]2/ri:M),{2af.-~[W'.I3+~']'#I)*][-2'\'_I2*4+*]]}fI~[~M)<']
M2m1e>'#*'.'-M3e<:D*][-3"|__"M*M2+M2*(e>:L<"_|"D~][_~~'_*][-3'#L)*
'/'_D*][L2+~'|'_D)*][L)~'/'_D2+*]]{{_0<{~S*}&}%s_W%1>"\/]""/\["erN}%


Newlines added to avoid scrolling. Try it online

Brief explanation:

The program builds the left half of the shrine (including the middle), then reverses it and replaces some characters to get the right half. A series of n spaces is represented as the number ~n (bitwise "not") during construction, and replaced with the actual spaces at the end.

The program starts with the top 2 lines, then for each roof level, it prepends all the previous lines with 2 spaces and adds the new roof (2 lines). The last roof is modified to add the "above door" part.

Next, the upper wall is built by repeating "|__" and truncating at the right length, followed by a fixed "_|" and spaces. The wall is then duplicated and the door spaces are replaced with underscores. Finally, the lower part is constructed line by line.

# Perl, 332 316 294

$:=($w=<>)*2+6;$r=2x($m=$w>3?3:$w);$k=1x($w-3).b.4x$m; y!a-f1-4!/.|\\[,#_ -!,/,/,s/(.*),(.*).{@{-}}/$2$1/,printf"%$:s%s
",y!/\\[!\\/]!r,(reverse=~s/.//r)for@x=(b,c,
(map{b33.3x$_.e.1x$_,"[#$k,"x/$w/.a__.22x$_}1..++$w),
_c.3x$m.f.($z=substr"|__"x$:,0,2*++$w),"_|$r,$z","d$r,".11x$w,c_.$r,d__.$r)


Try me.

# C, 371

d,i,w;char s[1<<24];m(){v(w,13);}p(){puts(s+1);}
v(i,j){s[w-i]=".|]\\#/"[j%7];s[w+i]=".|[/#\\"[j%7];
while(i--)s[w-i]=s[w+i]="# _-"[j/7];}
main(l){scanf("%d",&l);d=l>3?3:l;m(w=l*2+6);p(v(0,0));
for(v(0,1);i++<=l;v(i*2+2,17))p(),v(i*2+3,7),m(p(v(i,2)));v(l+2,2);p(v(d,21));
for(m(i=w-3);i>d+1;i-=3)v(i,15);p(v(d,8));p(v(d,15));
v(w-3,4);m(p(v(d,19)));p(v(d+1,15));p(v(d+2,19));}


Try me.

# JavaScript, 365

The above can be translated almost 1 to 1 into JavaScript:

s=[];r="";i=0;m=()=>v(w,13);p=()=>r+=s.join('')+"\n";
v=(i,j)=>{s[w-i]=".|]\\#/"[j%7];s[w+i]=".|[/#\\"[j%7];
while(i--)s[w-i]=s[w+i]="# _-"[j/7|0];};
f=l=>{d=l>3?3:l;m(w=l*2+6);p(v(0,0));
for(v(0,1);i++<=l;v(i*2+2,17))p(),v(i*2+3,7),m(p(v(i,2)));v(l+2,2);p(v(d,21));
for(m(i=w-3);i>d+1;i-=3)v(i,15);p(v(d,8));p(v(d,15));
v(w-3,4);m(p(v(d,19)));p(v(d+1,15));p(v(d+2,19));}


Use:

f(2);console.log(r)

• The C version crashes for sizes above 12. Since it looks like you're using a fixed size string to hold temporary results, I think you'll always have an upper limit, no matter how you choose the size of s. Unless you allocate it dynamically, of course. – Reto Koradi May 24 '15 at 15:44
• @RetoKoradi, Yes you are right, I posted version with a small buffer by mistake. But in the end, unless it is dynamically allocated there always will be a limit. – nutki May 24 '15 at 15:56

# Python 2, 356352347 344 bytes

n=input()
A,B,C,D,E,F,G,H,I='_ |\/#.]['
def p(*S):
for s in S:print(5+2*n-len(s)/2)*B+s
p(G,C,'.   ]#[   .')
for i in range(n):b=B*(4+i);p(D+A*(7+4*i)+E,G+b+H+F*(3+2*i)+I+b+G)
d=2*min(3,n)-1
a=A*(2+i)
f=F*(1+i-d/2)
j=4+2*i-d/2
w=('|__'*n)[:j-1]+A+C
v=w[::-1]
p(D+a+H+f+G+'-'*d+G+f+I+a+E,w+B*d+v,w+A*d+v,F*j+E+A*d+D+F*j,C+A*(d+2)+C,E+A*(d+4)+D)


This basically builds the shrine line by line. The function p prints a string with the spaces needed to center it.

I used python 2 to save lots of bytes, because the python 3 map object doesn't trigger. I guess I should always golf in python 2, just saves a few more bytes (even if it's just to not have to parse the input to int). Hehehe, it's not like code's pretty for golfing in the first place.

Edit: and of course, I now don't need the map anymore...

Here's the code in ungolfed form:

n = int(input())

# A function to print strings centered
half_width = 5 + 2*n
def p(string):
spaces = ' ' * (half_width - len(string) // 2)
print(spaces + string)

# The rooftops
p('.')
p('|')
p('.   ]#[   .')
for i in range(n):
p('\\' + '_'*(7 + 4*i) + '/')
p('.{0}]{1}[{0}.'.format(' '*(i + 4), '#'*(3 + 2*i)))

# The bottom rooftop
door_width = 2 * min(3, n) - 1
# (11+4i - (3+2i) - 4) / 2 = (4 + 2i) / 2 = 2 + i
p('\{0}]{1}.{2}.{1}[{0}/'.format('_'*(2 + i), '#'*(1 + i - door_width // 2), '-'*door_width))

# The windows
w = '|__'*n
w = w[:4 + 2*i  - door_width // 2]
if w[-1] == '|':
w = w[:-1] + '_'
w += '|'
p(w + ' '*door_width + w[::-1])
p(w + '_'*door_width + w[::-1])

# The foundation and the stairs
w = '#'*(4 + 2*i - door_width // 2)
p(w + '/' + '_'*(door_width) + '\\' + w)

# The remaining stairs
p('|' + '_'*(door_width + 2) + '|')
p('/' + '_'*(door_width + 4) + '\\')

• Since you're using Python 2 you can change print(B*(5+2*n-len(s)//2)+s) into print B*(5+2*n-len(s)/2)+s (remove parentheses and change // into /). – ace_HongKongIndependence May 22 '15 at 19:22
• Thanks @ace, didn't know python2 ignored float division. – Matty May 22 '15 at 19:38
• @Matty It doesn't ignore float division. You're performing division on integers, so the result is an integer. It only does float division if one or more operands is a float. – mbomb007 May 22 '15 at 21:58
• If you rearrange the order of print B*(5+2*n-len(s)/2)+s to print(5+2*n-len(s)/2)*B+s, you can remove the space after print. – isaacg May 22 '15 at 23:51

# JavaScript (ES6), 440

Edit Fixed lintel bug

A function whith height as a parameter, output to console.

Using template string a lot, all newlines are significant and counted.

Run snippet to test in Firefox (with console output)

f=x=>{R=(n,s=0)=>' #_-'[s][Z='repeat'](n),M=c=>R(2)+'|__'[Z](z+1).slice(0,z-1)+'_|'+R(y,c)+'|_'+'__|'[Z](z+1).slice(1-z)
for(z=x+x+(x<2)+(x<3),y=x>2?5:x>1?3:1,l=-1,o=${t=R(x+x+5)}.${t}|
;l++<x;)o+=${t=R(x+x-l-l)}.${u=R(l+3)}]${R(l*2+1,1)}[${u}.
${t}\${l-x?R(7+l*4,2):{t=R(x+1,2)}]{u=R(x<3||x-2,1)}.{R(y,3)}.{u}[{t}}/ ;console.log({o+M(0)} {M(2)} {R(2)}{t=R(z,1)}/{u=R(y,2)}\${t}${R(1+z)}|__${u}|${R(z)}/____${u}\\)} // TEST f(1),f(2),f(3),f(4),f(5),f(6) Output 1 to 6 in console Ungolfed version for interactive test: // Not so golfed f=x=>{ R=(n,s=0)=>' #_-'[s].repeat(n); // base building blocks M=c=>R(2)+'|__'.repeat(z+1).slice(0,z-1)+'_|'+R(y,c)+'|_'+'__|'.repeat(z+1).slice(1-z); // manage door level z=x+x+(x<2)+(x<3); // door and stairs surroundings y=x>2?5:x>1?3:1; // door and stairs width o = ${R(x+x+5)}.\n${R(x+x+5)}|\n; // top for(l=-1;l++<x;) o += ${ // even row
t=R(x+x-l-l) // left padding
}.${ u=R(l+3) }]${
R(l*2+1,1)
}[${ u }.\n${ // end even row, start odd row
t // left padding
}\${ l-x?R(7+l*4,2) :{t=R(x+1,2)}]{u=R(x<3||x-2,1)}.{R(y,3)}.{u}[{t} // if last row before the door, insert lintel }/\n; o += { M(0) // door level row 1 }\n{ M(2) // door level row 2 }\n{ R(2)}{t=R(z,1)}/{u=R(y,2)}\${t  // stairs row 1
}\n${ R(1+z)}|__${u  // stairs row 2
}|\n${ R(z)}/____${u // stairs row 3
}\\;

out(o)
}

out=x=>O.innerHTML=x

f(3)
<input id=I value=3><button onclick='f(+I.value)'>-></button><br>
<pre id=O></pre>

# Haskell, 473 bytes

g '\\'='/'
g '/'='\\'
g '['=']'
g ']'='['
g x=x
z=reverse
d=min 3
m n s=putStrLn$(6+2*n+1-length s)#' '++map g(z s)++tail s n#c=replicate n c t 0=".";t n=n#'#'++"["++(2+n)#' '++"." r 0="|";r n=(2+2*n)#'_'++"/" q n=d n#'-'++"."++max(n-2)1#'#'++"["++(n+1)#'_'++"/" e i n=d n#i++"|_"++z(take(max(n+2)(2*n-1))(cycle"|__")) b n=d n#'_'++"\\"++max(2*n)(3+n)#'#' w i n=(d n+1+i)#'_'++["|","\\"]!!i f n=mapM_(m n)$[u k|k<-[0..n],u<-[t,r]]++(t(n+1):map(\$n)[q,e ' ',e '_',b,w 0,w 1])

• OK thanks. Looks correct now – Damien May 23 '15 at 13:22
• I think it's OK now. btw, the base in your N=1 shrine has one more # – Damien May 23 '15 at 13:38
• Yup, works now. Fixed that extra unintended # – Optimizer May 23 '15 at 13:52

## C, 660 bytes

The pattern just seemed to be too irregular to come up with anything fancy, particularly in a language without string processing. So here is my brute force approach:

m,d,w,k,j;r(n,c){for(j=0;j++<n;)putchar(c);}c(char*s){for(;*s;)putchar(*s++);}f(n){m=n*2;d=n<3?m-1:5;w=m-d/2+2;r(m+5,32);c(".\n");r(m+5,32);c("|\n");for(;;){r(m-k*2,32);c(".");r(k+3,32);c("]");r(k*2+1,35);c("[");r(k+3,32);c(".\n");if(k==n)break;r(m-k*2+1,32);c("\\");r(k++*4+7,95);c("/\n");}c(" \\");r(n+1,95);c("]");r(n-d/2,35);c(".");r(d,45);c(".");r(n-d/2,35);c("[");r(n+1,95);c("/\n");for(k=0;k<2;){c("  ");for(j=0;j<w/3;++j)c("|__");c("|_|"-w%3+2);r(d,k++?95:32);c(!w%3?"|":w%3<2?"|_":"|_|");for(j=0;j<w/3;++j)c("__|");c("\n");}c("  ");r(w,35);c("/");r(d,95);c("\\");r(w,35);c("\n");r(w+1,32);c("|");r(d+2,95);c("|\n");r(w,32);c("/");r(d+4,95);c("\\\n");}


Before golfing:

#include <stdio.h>

void r(int n, int c) {
for (int i = 0; i++ < n; )
putchar(c);
}

void c(char* s) {
for (; *s; ++s) putchar(*s);
}

int f(int n) {
int m = n * 2;
int d = n < 3 ? m - 1 : 5;
int w = m - d / 2 + 2;

r(m + 5, 32);
c(".\n");

r(m + 5, 32);
c("|\n");

for (int k = 0; ; ++k) {
r(m - k * 2, 32);
c(".");
r(k + 3, 32);
c("]");
r(k * 2 + 1, 35);
c("[");
r(k + 3, 32);
c(".\n");

if (k == n) break;

r(m - k * 2 + 1, 32);
c("\\");
r(k * 4 + 7, 95);
c("/\n");
}

c(" \\");
r(n + 1, 95);
c("]");
r(n - d / 2 , 35);
c(".");
r(d, 45);
c(".");
r(n - d / 2 , 35);
c("[");
r(n + 1, 95);
c("/\n");

for (int k = 0; k < 2; ++k) {
c("  ");
for (int j = 0; j < w / 3; ++j)
c("|__");
c("|_|" - w % 3 + 2);
r(d, k ? 95 : 32);
c(!w % 3 ? "|" : w % 3 < 2 ? "|_" : "|_|");
for (int j = 0; j < w / 3; ++j)
c("__|");
c("\n");
}

c("  ");
r(w, 35);
c("/");
r(d, 95);
c("\\");
r(w, 35);
c("\n");

r(w + 1, 32);
c("|");
r(d + 2, 95);
c("|\n");

r(w, 32);
c("/");
r(d + 4, 95);
c("\\\n");

return 0;
}


Not much to explain here. It just goes line by line, and generates the necessary count of each character. I tried to keep the code itself compact, but it still adds up. d is the width of the door, w the width of each brick wall.

• c(char*s){for(;*s;)putchar(*s++);} ==> #define c printf; r(n,c){for(j=0;j++<n;)putchar(c);} ==> r(n,C){while(n--)putchar(C);} – ace_HongKongIndependence May 23 '15 at 22:47