14
\$\begingroup\$

Given three integers >= 2, create an ASCII cube in an orthogonal (cabinet) projection. The three integers represent height, width and depth (measured in visible characters) including the corners. The corners should be 'o's or '+', free choice.

w: 10, h: 5, d: 4 Thus gives:

   o--------o
  /        /|
 /        / |
o--------o  |
|        |  o
|        | /
|        |/
o--------o

Now, to make this slightly harder, all faces can either be solid, transparent or missing. We order the faces like this:

   o--------o
  /        /|
 /    2   / |
o--------o 3|
|        |  o
|   1    | /
|        |/
o--------o

  ---
  |2|
-------
|5|1|3|
-------
  |4|
  ---
  |6|
  ---

And supply a list of tokens, S, T or M. The original example is thus:

w 10
h 5
d 4
S S S S S S

   o--------o
  /        /|
 /        / |
o--------o  |
|        |  o
|        | /
|        |/ 
o--------o

If one face is transparent, we can see anything that is behind it:

T S S S S S

   o--------o
  /        /|
 /        / |
o--------o  |
|  o-----|  o
| /      | /
|/       |/
o--------o


T T T T T T

   o--------o
  /|       /|
 / |      / |
o--------o  |
|  o-----|--o
| /      | /
|/       |/
o--------o

For pairs of missing faces, adjacent edges or corners are no longer visible:

M M S S S S

   o--------o
  /|       /|
 / |      / |
o  |     o  |
|  o-----|  o
| /      | /
|/       |/
o--------o

M M S S M S

   o--------o
   |       /|
   |      / |
   |     o  |
   o-----|  o
  /      | /
 /       |/
o--------o

Code golf, shortest code wins! Trailing spaces and newlines are fine, you're free to choose input method and input order.

\$\endgroup\$
4
  • 5
    \$\begingroup\$ How strict is your input format? can I make a function with 9 parameters? \$\endgroup\$
    – LiefdeWen
    Commented Jun 15, 2017 at 14:36
  • 1
    \$\begingroup\$ @LiefdeWen you're free to choose input method and input order. And as nothing says otherwise, any of the default input/output methods can be used. \$\endgroup\$
    – dzaima
    Commented Jun 15, 2017 at 15:10
  • \$\begingroup\$ Can I take an integer as bitmap for the transparent/solid flags? \$\endgroup\$
    – Titus
    Commented Jun 20, 2017 at 5:45
  • \$\begingroup\$ @Titus Well.. alright. I guess it's a bit more entertaining if you actually can test the values by your self. \$\endgroup\$
    – NiklasJ
    Commented Jun 22, 2017 at 14:15

3 Answers 3

5
\$\begingroup\$

Charcoal, 190 181 bytes

NωA⁻ω²ςNηA⁻η²γNδA⁻δ²χA⪪S αF›⊟αMF⟦ςγςγ⟧«oκ↶»F∧›⊟αM²«oς↷³oχ↷¹»F∧›⊟αM²«↷³oχ↷³oγ↶»M⁻ωδ⁻δηF⁼§α²SG↗δ↓η↙δ↑η F∧›⊟αM²«↶¹oχ↷³oγ↷»F⁼§α¹SG↗δ←ω↙δ→ω F∧›⊟αM²«↶¹oχ↶³oς»F⁼§α⁰SUO±ωη ↷F›⊟αMF⟦γςγς⟧«oκ↷

Try it online! Link is to verbose version of code. Edit: Saved 9 bytes by optimising my conditions. Charcoal has no else token, so if commands always have two alternatives, unless they're at the end of a block or program. To avoid this, I use for (<bool>) instead of if (<bool>) which has a similar effect when the expression can only have the values 0 or 1 but saves a byte. (In order to achieve this I had to change the expressions so that they were always true when the body needed to be executed.) I was also able to optimise if (<bool>) for (<int>) into for (And(bool, int)).

\$\endgroup\$
7
  • \$\begingroup\$ Holy Christ O_O. I couldn't even figure out how to draw the cube itself using charcoal. Can you put up an example to draw a simple cube on the github examples folder? One that's been optimized? I want to compare my like... 50 byte answer to what it should've been. \$\endgroup\$ Commented Jun 16, 2017 at 21:09
  • \$\begingroup\$ @carusocomputing Sorry, I'm unclear as to what you mean by "simple cube", and I'm not an author of Charcoal itself, so I can't add an example. \$\endgroup\$
    – Neil
    Commented Jun 16, 2017 at 21:26
  • \$\begingroup\$ You aren't?! Holy crap, who is? I honestly thought you were. Also, I'd ask to be a charcoal contributor. You could easily become one on github :). You're talented in the language, obviously. And by "simple cube" I mean the first half of the challenge, just making an X * Y * Z ASCII cube. \$\endgroup\$ Commented Jun 16, 2017 at 21:50
  • \$\begingroup\$ @carusocomputing ASCII-only is the main contributor as far as I can tell, although the esolang wiki does credit a second contributor. \$\endgroup\$
    – Neil
    Commented Jun 16, 2017 at 21:51
  • \$\begingroup\$ at the very least I'd contact them with a few of your examples, you've taken it further than anyone else I've seen. I'd love to get more explanations of your code, I've followed your Charcoal answers for a bit now because the language is interesting to me. \$\endgroup\$ Commented Jun 16, 2017 at 21:53
2
\$\begingroup\$

JavaScript (ES6), 318 314 308 bytes

Takes width, height and depth as integers and the faces as an array of characters.

(w,h,d,l,M=(n,F)=>[...Array(n+1).keys()].map(F),a=M((L=w--+d)*(h--+--d),i=>++i%L?' ':`
`),D=(t,Y=0,X=d,W=t&1?d:w,H=t&2?d:h,F=l[t>>2])=>F>'R'&&M(W,i=>M(H,j=>a[p=L*(Y+j-i*(t&1))+X+i-(t&2?j:0)]=(x=!(i&&i-W)|2*!(j&&j-H))?' |-o|/o/-o'[t%4*3+x]:a[F>'S'?p:0])))=>D(20)&D(D(14,h)&D(17,d,0),d,D(9,d,w)&D(6))||a.join``

How?

The function M() processes a given callback F on a given range [0...n].

M = (n, F) => [...Array(n + 1).keys()].map(F)

The variable a holds a flat array representing a grid of size (w+d) x (h+d-1). It is initially filled with rows of spaces terminated with newlines.

a = M((L = w-- + d) * (h-- + --d), i => ++i % L ? ' ' : '\n')

The function D() is used to 'draw' a face of the cuboid.

The two least significant bits of the parameter t hold the face type:

  • 0 = rear / front
  • 1 = left / right
  • 2 = bottom / top

Bits #2 to #4 hold the 0-based face index.

D = (                                           // given:
  t, Y = 0, X = d,                              // - the type and the initial coordinates
  W = t & 1 ? d : w,                            // - the drawing width
  H = t & 2 ? d : h,                            // - the drawing height
  F = l[t >> 2]                                 // - the character representing the status
) =>                                            //
  F > 'R' &&                                    // provided that the face is not missing:
  M(W, i =>                                     // for each i in [0...W]:
    M(H, j =>                                   //  for each j in [0...H]:
      a[                                        //    update the output
        p = L * (Y + j - i * (t & 1)) +         //    at position p
            X + i - (t & 2 ? j : 0)             //
      ] =                                       //    with either:
      (x = !(i && i - W) | 2 * !(j && j - H)) ? //    - '|', '-' or '/' on edges
        ' |-o|/o/-o'[t % 4 * 3 + x]             //    - or 'o' on vertices
      :                                         //
        a[F > 'S' ? p : 0]                      //    - or a space on solid faces
    )                                           //    - or the current character on
  )                                             //      transparent faces

Faces are drawn in the following order:

D(5 * 4 + 0, 0, d)  // face #5 (rear)
D(3 * 4 + 2, h, d)  // face #3 (bottom)
D(4 * 4 + 1, d, 0)  // face #4 (left)
D(2 * 4 + 1, d, w)  // face #2 (right)
D(1 * 4 + 2, 0, d)  // face #1 (top)
D(0 * 4 + 0, d, 0)  // face #0 (front)

Demo

let f =

(w,h,d,l,M=(n,F)=>[...Array(n+1).keys()].map(F),a=M((L=w--+d)*(h--+--d),i=>++i%L?' ':`
`),D=(t,Y=0,X=d,W=t&1?d:w,H=t&2?d:h,F=l[t>>2])=>F>'R'&&M(W,i=>M(H,j=>a[p=L*(Y+j-i*(t&1))+X+i-(t&2?j:0)]=(x=!(i&&i-W)|2*!(j&&j-H))?' |-o|/o/-o'[t%4*3+x]:a[F>'S'?p:0])))=>D(20)&D(D(14,h)&D(17,d,0),d,D(9,d,w)&D(6))||a.join``

let update = _ => O.innerHTML = f(W.value, H.value, D.value, [...F.value])
update()
<label>Width <input id="W" size="3" value="10" oninput="update()" /></label>
<label>Height <input id="H" size="3" value="5" oninput="update()" /></label>
<label>Depth <input id="D" size="3" value="4" oninput="update()" /></label>
<label>Faces <input id="F" size="6" value="MMSSMS" oninput="update()" /></label>
<pre id="O"></pre>

\$\endgroup\$
1
\$\begingroup\$

SOGL V0.11, 200 194 193 192 190 bytes

b³@*⁶
ž}1}X⁵
;aκ⁴
2-³
* o1Ο²
d=?a³:?∫:¹
be.Aā6∫D,ζLI%:C?abe"DCa∫:c+H⁴d+ /ž}{"a+Hy"e³┐²čž|"b³┌²žz"EBAøp”,ōkB°s9θW=*↑(⅜⅞~υ=\⁰ōwūΧ►ΣΤP░¶Ο⁽◄Φ7⅟▲s#‘┌Θdwι+#¶ŗ!!6c=?6d=?2aI⁶e³∙ž}5¹b+⁴Ie³@∙⁵}4¹2+⁴⁶⁵

Takes input in the order

width
height
depth
down-face
left-face
back-face
top-face
right-face
front-face

Tied!
Try it Here! (compressed value changed to be V0.12 compatible)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.