17
\$\begingroup\$

Given an integer greater than or equal to 2, output ASCII-art resembling an isometric-perspective cube ring with that side length.

Expected outputs given below for 2, 3. You can imagine the rest. You may alternatively consider the first example to be output for 1, second to be output for 2, etc.

This is , shortest code wins. Your output may include any additional whitespace that does not impact the presentation of the image.

2

   / \ / \
  |\ /|\ /|
  | | | | |
 / \|/ \|/ \
|\ /|   |\ /|
| | |   | | |
 \|/ \ / \|/
  |\ /|\ /|
  | | | | |
   \|/ \|/

3
                     
     / \ / \ / \     
    |\ /|\ /|\ /|    
    | | | | | | |    
   / \|/ \|/ \|/ \   
  |\ /|       |\ /|  
  | | |       | | |  
 / \|/         \|/ \ 
|\ /|           |\ /|
| | |           | | |
 \|/ \         / \|/ 
  |\ /|       |\ /|  
  | | |       | | |  
   \|/ \ / \ / \|/   
    |\ /|\ /|\ /|    
    | | | | | | |    
     \|/ \|/ \|/     
\$\endgroup\$
1
  • \$\begingroup\$ I think a few ascii-art challenges are quite similar to this, but I can't find any examples offhand. \$\endgroup\$ Commented Jul 10 at 10:22

9 Answers 9

8
\$\begingroup\$

Charcoal, 41 bytes

NθF²F³Fθ«F³M∨μ¹✳⁺×⁴ι×μ⁻¹κP↑”{⊟∨÷IDR▶#⟲⁹⁰e

Try it online! Link is to verbose version of code. Uses the alternative input scheme where the input is a sixth of the number of cubes. Explanation:

Nθ

Input the integer.

F²F³

Repeat for each of six directions, represented as two major directions (right and left) and three minor directions (-60, 0 and +60 degrees).

Fθ«

Repeat the given integer times.

F³M∨μ¹✳⁺×⁴ι×μ⁻¹κ

Move to the next cube.

P↑”{⊟∨÷IDR▶#⟲⁹⁰e

Output the cube. The cube is output in an upwards direction to avoid accidentally overwriting a cube above. Given that there are 12 characters to output, a 14-byte compressed string seems as if it will be more efficient than trying to use drawing commands.

The directions moved in each inner loop are respectively:

  • N, N, NE, E (in reverse order)
  • E, E, E, E
  • E, SE, S, S
  • S, S, SW, W (in reverse order)
  • W, W, W, W
  • W, NW, N, N
\$\endgroup\$
8
\$\begingroup\$

sed 4.2.2, 573 572 bytes

h;s!.! / \\!g;x;s/.//;s/./  /g;G;s/\n//p
s! /!|/!g;y|\\/|/\\|;s/$/|/p;h
s!\\ /! | !gp
x;s! /|!|/ !g;:a;s!$!\\!;s! |!/ !p
s/  \\/   /;s!/  !   !;y!/\\!\\/!;:e
s!|\\ /|!|   |!;s/ | /   /;te;s! \\!|\\!;s/$/|/p
s!\\ /! | !gp
s!| | |!|\\|/ !;s!! \\|/ !
/^ *  |/ta;:b;s/\n.*//
s!/  !/ \\!
s/^|/ /;s! \? \\|!/ \\|!2p
y|\\/|/\\|;s!/! !;s!\\ $!!;s!/ !/|!;s! \\!|\\!;p
s!\\ /! | !gp
s!| | |! \\|/ !g;T;s! | |!\\|/!;t
G;s/ *| | /  /g;s/   |/\\/
T;s/^\( *\\\).*\n\1/&/;Tb
s/\n.*//;:z;s!/    !/ \\ /!;tz;p
y!/\\!\\/!;s!/! !;s!\\ $!!;s!/ \\!/|\\!gp
s!\\ /! | !gp
s!| | ! \\|/!g;s/|$//;:

Try it online!

takes input as any unary character. works for inputs of 2 or more. basically it just outputs each line after it makes it. the little 'humps' between outputs in the test cases is the output for an input of 0; you can remove the extra newlines in the input if you want to see the output without them.

here's with trying to output three lines at a time:

sed 4.2.2, 566 bytes

h;s!.! / \\!g;x;s/.//;s/./  /g;G;s/\n//p
s! /!|/!g;y|\\/|/\\|;s/$/|/p;h
s!\\ /! | !gp
x;s! /|!|/ !g;:a;s!$!\\!;s! |!/ !p
s!/ \\|!    !g;x;s/|.*//;G;s!..\(.*\)\n\1!\1|\\ /|!
s!      / \\!|\\ /|!
s/.*/&\n&\n&/
s!|\\ /|!| | |!3g
T;s! | | |!/ \\|/ !3;Tr
s!| | |! \\|/ \\!3;bh
:a;p;s/^  //mg;s!/  \||  !&    !mg;:h;/^  /ta
:r;s/ |\n.*/ |/
s!| | | \( *\) | | |!&\n \\|/ \\\1/ \\|/!;be
:k;s/^/  /gm;s!\\    !\\!;s!|    !|!g
:e;s!\n[^\n]*$!&&!;G;s![^ \n]! !23g
T;s!\n\( *\)\n\1!!;t;s/\n *\n *//p;tk
:;s!\\    !\\ / \\!;t;p;s/^/  /gm;s/|  .*//gm;s!/ \\.*$!/!
:q;s/....$/&&/mg

Try it online!

this one doesn't work yet (the last line of cubes is proving particularly hard to measure) but doing it this way might make it easier to golf.

\$\endgroup\$
6
\$\begingroup\$

K (ngn/k), 79 bytes

{`0:"\\/|"(3|=8*x).[;;&;+5 4#4\3947690525]/(x+x+!'4 5)+\+-4+9\,/1_'x#'",EA$"}

Try it online!

Inserts one cube at a time in clockwise order: "animation"

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 176 bytes

Builds the output character by character.

n=>(y=h=n*6-2,n+=n-1,g=x=>y?`| /\\
`[X=w-x-n,s=y>h/2,c=x-n>4&X>4,~x?x--<n|X<0|y>4&y<h-3&c||`03123${y/h|y==4*c}210101`[y%3*4|X-y%3*s*2&3]:(n+=y--%3&&-s|1,x=w,4)]+g(x):"")(w=n*4)

Try it online!

Variables

Below are the most important variables used in the code:

  • \$x\$ : current column, initialized to the width \$w=8n-4\$
  • \$y\$ : current row, initialized to the height \$h=6n-2\$
  • \$y \bmod 3\$ : cube row (1 = top, 0 = middle, 2 = bottom)
  • \$s\$ : side (1 = top half / 0 = bottom half)
  • \$p\$ : left/right padding, initialized to \$2n-1\$ (the name \$p\$ is used here for clarity; in the code, we actually re-use the input variable \$n\$)
  • \$c\$ : a flag set when we are located in the center part

For \$n=3\$, this leads to the following diagram:

x=20                 x=-1
 |                    |  |  y | y%3 | s | p
-v--------------------v--+----+-----+---+---
 ...../.\./.\./.\.....\n | 16 |  1  | 1 | 5
 ....|\./|\./|\./|....\n | 15 |  0  | 1 | 4
 ....|.|.|.|.|.|.|....\n | 14 |  2  | 1 | 4
 .../.\|/.\|/.\|/.\...\n | 13 |  1  | 1 | 3
 ..|\./|ccccccc|\./|..\n | 12 |  0  | 1 | 2
 ..|.|.|ccccccc|.|.|..\n | 11 |  2  | 1 | 2
 ./.\|/ccccccccc\|/.\.\n | 10 |  1  | 1 | 1
 |\./|ccccccccccc|\./|\n |  9 |  0  | 1 | 0
 |.|.|ccccccccccc|.|.|\n |  8 |  2  | 0 | 0
 .\|/.\ccccccccc/.\|/.\n |  7 |  1  | 0 | 1
 ..|\./|ccccccc|\./|..\n |  6 |  0  | 0 | 2
 ..|.|.|ccccccc|.|.|..\n |  5 |  2  | 0 | 2
 ...\|/.\./.\./.\|/...\n |  4 |  1  | 0 | 3
 ....|\./|\./|\./|....\n |  3 |  0  | 0 | 4
 ....|.|.|.|.|.|.|....\n |  2 |  2  | 0 | 4
 .....\|/.\|/.\|/.....\n |  1 |  1  | 0 | 5

Commented

n => (                    // n = input
  y = h = n * 6 - 2,      // initialize y and h to 6n - 2
  n += n - 1,             // turn n into the padding, initialized to 2n - 1
  g = x =>                // g = recursive function taking x
  y ?                     // if y is not 0:
    `| /\\\n`[            //   lookup string of possible characters
      X = w - x - n,      //   set X = w - x - n
      s = y > h / 2,      //   set s = 1 for top half / 0 for bottom half
      c = x - n > 4 &     //   set c if we're in the center of the row,
          X > 4,          //   i.e. x - n > 4 and X > 4
      ~x ?                //   if x is not equal to -1:
        x-- < n | X < 0 | //     append a space if we're too far to the left,
        y > 4 &           //     too far to the right, or in the center of
        y < h - 3 & c     //     the pattern
        || (              //     otherwise, use a cube pattern:
          `0312` +        //       "|\ /" for the middle row
          `3${y / h |     //       either "\|/ " or "\ / " for the top row
              y == 4 * c  //       (depending on y and c)
          }21` +          //
          `0101`          //       or "| | " for the bottom row
        )[  y % 3 * 4 |   //     get the position of the pattern
            X -           //     get the position of the character in the
            y % 3 * s * 2 //     pattern
            & 3 ]         //
      :                   //   else (end of row):
        ( n += y-- % 3    //     add -1, 0 or 1 to the padding
              && -s | 1,  //
          x = w,          //     reset x to w
          4 )             //     append a line-feed
    ] + g(x)              //   append the result of a recursive call
  :                       // else (end of recursion):
    ""                    //   stop
)(w = n * 4)              // initial call to g with x = w = 4n
\$\endgroup\$
4
\$\begingroup\$

Python 3.8 (pre-release),  314   259   239   233   229   197   189  183 bytes

-55 bytes by encoding the character positions as a list.
-20 bytes by cheating returning a 2D list, thanks to noodle person.
-6 bytes by using unprintables.
-4 bytes by using [0]*n instead of range(n).
-40 bytes by Jonathan Allan.
-6 bytes by xnor.

No, I don't know how it works either.

def f(n):
 x=2*n;l=[7*x*[s]for s in' '*5*x];y=N=0
 for v in b'cV6#0P':
  for _ in[0]*n:
   for t in b'\12	':l[y+t//5][x+t%5]='\/||'[N%4];N+=1
   x+=v//8-8;y+=v%8-3
 return l

First example is inputted as 1.
The \12 in the unprintable string is literal.

Try it online!

\$\endgroup\$
6
  • \$\begingroup\$ Nice solution! You can just return l, no need to print each line \$\endgroup\$ Commented Jul 10 at 19:19
  • \$\begingroup\$ @noodleperson: I don't think that would count in an [ascii-art] challenge. \$\endgroup\$ Commented Jul 10 at 19:21
  • 2
    \$\begingroup\$ It's pretty common for [ascii-art] function-submissions to return an array of strings instead of a multiline string, and an array of characters is the same as a string, so a 2d array of characters is totally acceptable \$\endgroup\$ Commented Jul 10 at 19:27
  • 1
    \$\begingroup\$ ...another 8 by avoiding enumerate and using x a little earlier - TIO \$\endgroup\$ Commented Jul 11 at 1:26
  • 1
    \$\begingroup\$ You can initialize l=[7*x*[s]for s in' '*5*x] for -6 bytes \$\endgroup\$
    – xnor
    Commented Jul 12 at 0:13
3
\$\begingroup\$

Regenerate, 318 bytes

( {2*$~1-2}) ( / \\){$~1}
($1 (\|\\ /){$~1}\|
)($1( \|){#1+3}
)$1/( \\\|/){$~1} \\(
( {#9-2}! {#1-2})( $4\|)( {8*$~1-14-2*#9})$10
$9($6{3})$11$12
$9/$7 $11 $7 \\){$~1-2}
 $4\|( {8*$~1-14}) $4\|
$6{3}$13$6{3}(
($15  ! )$7 \\ ( {#16-4}!$11)  /$7
$15 $10$16$10
$15 $12$16$12){$~1-2}
$1\\\|/( \\ /){$~1-1}$7
$3$5 $1$7{$~1}

Attempt This Online!

Generates the figure line by line. With reference to the N = 3 diagram, the output always contains one copy of the first four lines, then N-2 copies of the next three, then one copy of the next two, then N-2 copies of the next three, and finally one copy of the last four. These roughly correspond to the lines of the program, except that the last line of the program generates the last three lines of the output.

This could probably be a bit shorter, but right now I'm tired of counting backreferences. :P

\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 325 bytes

n=>{w=8*n-3
h=n*6-2
o=Array(h).fill(0).map(x=>Array(w).fill(' '))
q=(x,y)=>' / \\-|\\ /|-| | |- \\|/'.split`-`.map(j=>j.split``).map((f,g)=>f.map((l,m)=>o[y+g][x+m]=l))
for(e=0;e<n;e++){r=n*2-2+e*4
t=(n-e)*3
u=w-5-2*e
q(r,0)
q(r,6*n-6)
q(2*e,t-3)
q(2*(n-e)-2,h-3*e-4)
q(u,t-3)  
q(u,h-t-1)}return o.map(z=>z.join``).join`\n`}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Nice answer. You can save a few bytes by using h+~t instead of h-t-1 and 2*(n+~e) instead of 2*(n-e)-2 (relevant tip). Also, you can move the ++ to the final use of e, so you can remove the e++. In addition, you can remove the {} of the for-loop by putting everything inside the loop: try it online - 318 bytes. (And you also accidently had two spaces after the q(u,t-3).) EDIT: And removing variable w is also 2 bytes shorter: try it online - 316 bytes. \$\endgroup\$ Commented Jul 15 at 8:16
1
\$\begingroup\$

Ruby, 166 150 bytes

->n{w=6*v=n*4
s=(?.*w+$/)*w
w.times{|i|j=i%4
j<1&&v+=[4,w*3+5,w*3+1][i/4/n%3]*(1-i/n/12*2)
s[v-j*~w-~k=j%-3/2,l=3-k*2]='/ \  |\ /|| | |\|/'[j*5,l]}
s}

Try it online!

Function that returns a newline separated string.

Starts with a blank newline separated string, then adds one cube at a time, each cube built from 4 lines.

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

Elisp, 578 bytes

(setq s (+(*(- n 1)2)1))(defun o (s)(save-excursion(cl-loop for x below 5 do(if (not (= (or (char-after) ?\C-j) ?\C-j))(delete-char 1)))(insert s))(next-line))(defun d (x y)(goto-char (+ (* y (+ (* s 6)1)) x))(o " / \\ ")(o "|\\ /|")(o "| | |")(o " \\|/ "))(with-temp-buffer(newline (* s 3))(string-insert-rectangle 0 (point-max) (make-string (* s 6) ? ))(cl-loop for c to (1- s) do(let ((x (1+ (*(abs(-(/ s 2)c))2)))(y (* c 3)))(d x y)(d (+(1- (-(* s 3)x)) (1- s)) y)))(cl-loop for c to (- n 3) do(let ((x (+ s (* (1+ c) 4))))(d x 0)(d x (* (1- s) 3))))(princ (buffer-string)))

Had some fun drawing each cube one at a time instead of a "top down" approach. Huge respect to those that where able to do it that way

#!/usr/bin/emacs --script
(require 'cl-lib)
(setq next-line-add-newlines t)
(setq n (string-to-number (pop argv)))
(setq square-count (+(*(- n 1)2)1))
(defun overwrite (s)
  (save-excursion
  (cl-loop for x below 5 do
       (if (not (= (or (char-after) ?\C-j) ?\C-j))
       (delete-char 1)
     )
       )
  (insert s)
  )
  (next-line)
  )

(defun cube (x y)
  (message "drawing cube at %s %s" x y)
  (goto-char (+ (* y (+ (* square-count 6)1)) x))
  (overwrite " / \\ ")
  (overwrite "|\\ /|")
  (overwrite "| | |")
  (overwrite " \\|/ ")
  )

(with-temp-buffer
  (newline (* square-count 3))
  (string-insert-rectangle 0 (point-max) (make-string (* square-count 6) ? ))
  (cl-loop for c to (1- square-count) do
       (let ((x (1+ (*(abs(-(/ square-count 2)c))2)))
         (y (* c 3)))
     (cube x y)
     (cube (+(1- (-(* square-count 3)x)) (1- square-count)) y)
     ))
  ;; top and bot row
  (cl-loop for c to (- n 3) do
       (let ((x (+ square-count (* (1+ c) 4))))
     (cube x 0)
     (cube x (* (1- square-count) 3))
     )
       )

  (princ (buffer-string))
  )
\$\endgroup\$

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