15
\$\begingroup\$

Automatic house building nanobots have been fabricated, and it's your job to code them.

Here is the house created by input 7 4 2

  /-----/|
 /     / |
|-----|  |
|     |  |
|     | /
|_____|/

The input is a string containing the house's dimensions.

7 is the width.

|_____|

---7---

4 is the height.

|
|
|
|

2 is the depth

 / 
/

Given this input, can you create the house?

Your code must be as small as possible so that it can fit in the robots.

Notes

The smallest dimensions you will be given as input are 3 2 2. Your program can do anything with dimensions that are smaller than 3 2 2.

Testcases

3 2 10

          /-/|
         / / |
        / / /
       / / /
      / / /
     / / /
    / / /
   / / /
  / / /
 / / /
|-| /
|_|/
\$\endgroup\$
16
  • \$\begingroup\$ Related. \$\endgroup\$
    – Leaky Nun
    May 1, 2016 at 14:45
  • \$\begingroup\$ It is not a cube, so I think my question is separate enough. Could change chars though. \$\endgroup\$
    – user53397
    May 1, 2016 at 14:46
  • 2
    \$\begingroup\$ More testcases please? \$\endgroup\$
    – Leaky Nun
    May 1, 2016 at 14:47
  • 1
    \$\begingroup\$ Also, this is a nice question. I don't think we have one yet. \$\endgroup\$
    – Riker
    May 1, 2016 at 14:57
  • 1
    \$\begingroup\$ What would the output be for 3 2 10? \$\endgroup\$
    – Downgoat
    May 1, 2016 at 15:01

5 Answers 5

3
\$\begingroup\$

Python 2, 128 bytes

w,h,d=input();i=d
while-i<h:c='|/'[i>0];print' '*i+c+'- _'[(d>i!=0)+(h+i<2)]*(w-2)+c+' '*min(d-i,h-1,w+1,h-1+i)+'/|'[d-i<h];i-=1

Prints row by row. The row indices i count down from d to -h+1.

\$\endgroup\$
1
  • \$\begingroup\$ You can trim 3 bytes by replacing ' '*min(d-i,h-1,w+1,h-1+i) with (' '*d)[max(0,i):h-1+i] \$\endgroup\$
    – RootTwo
    May 8, 2016 at 4:19
1
\$\begingroup\$

Ruby, 145 bytes

Returns a list of strings. Each element in the list corresponds to a line. If a multiline string must be returned, add 3 bytes to add *$/ right before the last bracket.

->w,h,d{s=' ';(0..m=d+h-1).map{|i|(i<d ?s*(d-i)+?/:?|)+(i<1||i==d ??-:i==m ??_ :s)*(w-2)+(i<d ? ?/:?|)+(i<h ?s*[i,d].min+?|:s*[m-i,h-1].min+?/)}}
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 169 bytes

(w,h,d)=>[...Array(d+h--)].map((_,i)=>` `[r=`repeat`](i<d&&d-i)+(c=`|/`[+(i<d)])+` _-`[i&&i-d?h+d-i?0:1:2][r](w-2)+c+` `[r]((i<d?i:d)-(i>h&&i-h))+`|/`[+(i>h)]).join`\n`

Where \n represents a literal newline character. Explanation:

(w,h,d,)=>                          Parameters
[...Array(d+h--)].map((_,i)=>       Loop over total height = d + h
 ` `[r=`repeat`](i<d&&d-i)+         Space before roof (if applicable)
 (c=`|/`[+(i<d)])+                  Left wall/roof edge
 ` _-`[i&&i-d?h+d-i?0:1:2][r](w-2)+ Space, floor or eaves between walls
 c+                                 Right wall/roof edge (same as left)
 ` `[r]((i<d?i:d)-(i>h&&i-h))+      Right wall
 `|/`[+(i>h)]                       Back wall/floor edge
).join`                             Join everything together
`

Edit: Saved 2 bytes thanks to @jrich.

\$\endgroup\$
2
  • \$\begingroup\$ Try removing the ,r='repeat' from the front and replace the first [r] with [r='repeat'] \$\endgroup\$
    – jrich
    May 2, 2016 at 23:45
  • \$\begingroup\$ @jrich Thanks, I originally had ,r=(n,c=` `)=>c.repeat(n) and when I changed tack I overlooked the possibility for the rearrangement. \$\endgroup\$
    – Neil
    May 2, 2016 at 23:51
1
\$\begingroup\$

Python 224 301 297 Bytes

(Now Works for all boxes including 1x1x1)

l,w,h=input()
s,r,d,v,R,x=" "," - ","/","|",range,(l*3-1)
print s*(w+1)+r*l
for n in R(w):
    if n<h:e,c=v,n
    else:e,c=d,h
    print s*(w-n)+d+s*x+d+s*c+e
if h-w>=1:e,c=v,w
elif w>h:e,c=d,h
else:e,c=d,w
print s+r*l+s*c+e
for n in R(h):
    if h>w+n:e,c=v,w
    else:e,c=d,h-n-1
    print v+s*x+v+s*c+e
print r*l

Explanation:

Takes in three constants: l (length), h(height), w(width).

If we look at a couple sample boxes we can find patterns in the spacing.

For a 3 x 4 x 3 box, we will use numbers to represent spacing between sections.

1234 -  -  - 
123/12345678/|
12/12345678/1|
1/12345678/12|
1 -  -  - 123|
|12345678|123/
|       8|12/
|       8|1/
|       8|/
 -  -  - 

The top row has 4 spaces or which is w + 1. The Next three lines have w - (1 * x). X being the line.

These are patterns that continue throughout all lines in all boxes. Therefore, we can easily program this line by line, multiplying the number of spaces to fit the pattern.

Here is a sample for a 5 x 5 x2 box.

 123 -  -  -  -  -
 12/12345678912345/|
 1/              /1|
 1 -  -  -  -  - 12|
 |              |12|
 |              |12|
 |              |12|
 |              |1/
 |12345678912345|/
  -  -  -  -  -
\$\endgroup\$
5
  • \$\begingroup\$ You should probably keep golfing. \$\endgroup\$
    – Riker
    May 4, 2016 at 2:18
  • \$\begingroup\$ Also, you need to either assign w,h,l=input() or make this a function. \$\endgroup\$
    – Riker
    May 4, 2016 at 2:21
  • \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! We require all submissions to be either full programs that read from STDIN and write to STDOUT or functions that accept arguments and return values. We also require submissions to be serious contenders for winning at the time of posting, which means we don't allow ungolfed or partially ungolfed solutions for code golf. \$\endgroup\$
    – Alex A.
    May 4, 2016 at 2:22
  • \$\begingroup\$ When I run this code here, there are extra spaces in the output. \$\endgroup\$
    – DJMcMayhem
    May 4, 2016 at 18:34
  • \$\begingroup\$ @DrGreenEggsandHamDJ Fixed It! It didn't account for a certain pattern of h, w, and l so I added some if statements. \$\endgroup\$
    – JoshK
    May 7, 2016 at 0:59
0
\$\begingroup\$

Python 3.5, 328 326 313 305 295 248 bytes

(Thanks to Kevin Lau for the tip about reducing the size of the ternary statements!)

def s(w,h,d):R,M=range,max;S,V,L=' |/';O=w-2;D=d-M(0,d-h);Q=h-M(0,h-d);print('\n'.join([S*(d-i)+L+' -'[i<1]*O+L+S*[h-1,i][i<=D-1]+'/|'[i<=D-1]for i in R(D+M(0,d-h))]+[V+[' -'[i==h],'_'][i<2]*O+V+S*[i-1,d][i>Q]+'/|'[i>Q]for i in R(Q+M(0,h-d),0,-1)]))

Takes input as 3 integers in the order of width, height, depth. Will golf more over time wherever I can.

Try it online! (Ideone)

Explanation:

For the purposes of this explanation, assume the function was executed with the arguments (3,2,3) where 3 is the width (w), 2 is the height (h), and 3 is the depth (d). That being said, let me begin by showing the main part of the entire function:

'\n'.join([S*(d-i)+L+' -'[i<1]*O+L+S*[h-1,i][i<=D-1]+'/|'[i<=D-1]for i in R(D+M(0,d-h))]+[V+[' -'[i==h],'_'][i<2]*O+V+S*[i-1,d][i>Q]+'/|'[i>Q]for i in R(Q+M(0,h-d),0,-1)])

Here, the two lists that make up the entire "house" are created and then joined together by literal new lines (\n). Let's call them list a and list b respectively, and analyze each one of them:

  • Here is where list a is created:

    [S*(d-i)+L+' -'[i<1]*O+L+S*[h-1,i][i<=D-1]+'/|'[i<=D-1]for i in R(D+M(0,d-h))]
    

    This list contains the first d lines of the house. Here, i is each number in the range 0=>(d-(d-h))+d-h where d-h=0 if negative or zero. To start, d-i spaces are added to the list, followed by a / and then whatever is returned by a compressed conditional statement. In this conditional statement, w-2 number of spaces are returned if i>1. Otherwise the same number of - are returned. Then, these are followed up by another /, and then spaces, where the number of spaces now depends on whether or not i<=d-(d-h)-1. If it is, then i spaces are added. Otherwise, h-1 spaces are added. Finally, this is all topped off by either a / or a |, where | is added if i<=d-(d-h)-1, otherwise a / is added. In this case of a 3x2x3 prism, this would be returned by list a:

          /-/|
         / / |
        / / /
    
  • Here is where list b is created:

    [V+[' -'[i==h],'_'][i<2]*O+V+S*[i-1,d][i>Q]+'/|'[i>Q]for i in R(Q+M(0,h-d),0,-1)]`
    

    This lists contains the rest of the lines of the prism. In this list, i is each integer in the range (h-(h-d))+h-d=>0 where h-d=0 if negative or zero. To start this list off, firstly a | is added since these lines always start with a |. Then, either a space, -, or _ is added depending on whether or not i=h or i<2. If i<2, then a _ is added. Otherwise, a - is added if i=h, or a space is added if i>h or i<h or i>2. After this decision has been made, then w-2 number of the chosen character is added. After this, another | is added, and then either i-1 or d number of spaces are added. If i>h-(h-d), then a d number of spaces are added. Otherwise, i-1 number of spaces are added. Finally, this is all topped off with either a | or a /, in which a | is added if i>h-(h-d), or a / is added if i<=h-(h-d). In the case of a 3x2x3 prism, list b returns:

        |-| /
        |_|/
    

After the 2 lists have been created, they are finally joined with literal new lines (\n) using '\n'.join(). This is your completed prism, and in this case, would come to look like this:

       /-/|
      / / |
     / / /
    |-| /
    |_|/
\$\endgroup\$
7
  • 1
    \$\begingroup\$ Python booleans evaluate to integers, which means most of your ternaries can be compressed to things like '-_'[f<2]. Finally, R=range;S,V,L=' |/' works for assigning your initial variables since strings will gladly unpack themselves for you in that situation. \$\endgroup\$
    – Value Ink
    May 2, 2016 at 23:39
  • \$\begingroup\$ Never mind, I forgot that operator doesn't exist in Python... But the rest should work! \$\endgroup\$
    – Value Ink
    May 2, 2016 at 23:41
  • \$\begingroup\$ @KevinLau-notKenny Wow, thanks for the tips! :) I did not know that ternary expressions could be expressed in that way! \$\endgroup\$
    – R. Kap
    May 2, 2016 at 23:43
  • \$\begingroup\$ You can use that trick for ternaries so long as you aren't modifying variables inside it. For example, a=1 if b<9 else c=5 can't be expressed as [a=1,c=5][b<9] because you'll end up modifying both a and c. Here is the PPCG Python golfing tips page: codegolf.stackexchange.com/questions/54/… \$\endgroup\$
    – Value Ink
    May 2, 2016 at 23:49
  • \$\begingroup\$ You still have one ternary that's still there, '_'if f<2else' -'[f==h]. Remember booleans evaluate as integers, so you could "chain" this ternary to the other one you fixed to get [' -'[f==h],'_'][f<2]. Also, you haven't used my tip with S,V,L=' |/' yet. \$\endgroup\$
    – Value Ink
    May 3, 2016 at 4:09

Your Answer

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