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\$
  • \$\begingroup\$ Related. \$\endgroup\$ – Leaky Nun May 1 '16 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 '16 at 14:46
  • 2
    \$\begingroup\$ More testcases please? \$\endgroup\$ – Leaky Nun May 1 '16 at 14:47
  • 1
    \$\begingroup\$ Also, this is a nice question. I don't think we have one yet. \$\endgroup\$ – Rɪᴋᴇʀ May 1 '16 at 14:57
  • 1
    \$\begingroup\$ What would the output be for 3 2 10? \$\endgroup\$ – Downgoat May 1 '16 at 15:01
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.

| improve this answer | |
\$\endgroup\$
  • \$\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 '16 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+?/)}}
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Try removing the ,r='repeat' from the front and replace the first [r] with [r='repeat'] \$\endgroup\$ – jrich May 2 '16 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 '16 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|/
  -  -  -  -  -
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ You should probably keep golfing. \$\endgroup\$ – Rɪᴋᴇʀ May 4 '16 at 2:18
  • \$\begingroup\$ Also, you need to either assign w,h,l=input() or make this a function. \$\endgroup\$ – Rɪᴋᴇʀ May 4 '16 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 '16 at 2:22
  • \$\begingroup\$ When I run this code here, there are extra spaces in the output. \$\endgroup\$ – James May 4 '16 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 '16 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:

       /-/|
      / / |
     / / /
    |-| /
    |_|/
| improve this answer | |
\$\endgroup\$
  • 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 '16 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 '16 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 '16 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 '16 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 '16 at 4:09

Your Answer

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