21
\$\begingroup\$

Your task: make a hexagonal triangle with side length n, where n is a positive whole number or 0.

First, let me define a hexagon:

 / \
|   |
 \ /

(Amazing ASCII art, right?)

Hexagons can be linked together by sharing sides:

 / \ / \
|   |   |
 \ / \ /

   / \  
  |   |
 / \ /
|   |
 \ /

A hexagonal triangle is the following:

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

That hexagonal triangle has a side length of 2-- 2 hexagons are required to make one side. A hexagonal triangle with side-length 1 is just a single hexagon, and a hexagon with side-length 0 is empty.

More formally, a hexagonal triangle is a triangle made of hexagons linked by their sides. The top hexagon links to the two below it on its bottom two sides. The triangle in the bottom left links to the one to its right and top-right, and the one in the bottom right links to the ones on its left and upper left. There are hexagons in between the corner ones, connected by their opposite sides, and their number is n-2. The triangles are not filled.

More examples:

Side length 3:
     / \
    |   |
   / \ / \
  |   |   |
 / \ / \ / \
|   |   |   |
 \ / \ / \ /

Side length 4:
       / \
      |   |
     / \ / \
    |   |   |
   / \ / \ / \
  |   |   |   |
 / \ / \ / \ / \
|   |   |   |   |
 \ / \ / \ / \ /
(This triangle isn't really filled, the borders make it look like there is a hexagon in the middle, but there is not.)

Side length 5:
         / \
        |   |
       / \ / \
      |   |   |
     / \ / \ / \
    |   |   |   |
   / \ /     \ / \
  |   |       |   |
 / \ / \ / \ / \ / \
|   |   |   |   |   |
 \ / \ / \ / \ / \ /

Side length 6:
           / \
          |   |
         / \ / \
        |   |   |
       / \ / \ / \
      |   |   |   |
     / \ /     \ / \
    |   |       |   |
   / \ /         \ / \
  |   |           |   |
 / \ / \ / \ / \ / \ / \
|   |   |   |   |   |   |
 \ / \ / \ / \ / \ / \ /
\$\endgroup\$
8
  • 22
    \$\begingroup\$ If there isn't a Hexagony answer for this, I will lose all faith in @MartinEnder. \$\endgroup\$ Apr 23, 2017 at 20:00
  • \$\begingroup\$ @Soyoucanreplytomeincomments Let's just say if I could folow users on here, they'd be on the list. \$\endgroup\$
    – phyrfox
    Apr 23, 2017 at 20:04
  • 1
    \$\begingroup\$ @phyrfox You can, sort of. \$\endgroup\$
    – Dennis
    Apr 23, 2017 at 21:19
  • 2
    \$\begingroup\$ I expect to see a short answer in Charcoal. I'd do it myself, but I'd have to learn it first, and I want to watch a movie instead, sorry. \$\endgroup\$
    – Neil
    Apr 23, 2017 at 21:20
  • 3
    \$\begingroup\$ @Neil you are forgiven for not learning an entirely new programming language. But that's your first warning! \$\endgroup\$ Apr 23, 2017 at 21:58

7 Answers 7

11
\$\begingroup\$

Charcoal, 62 43 39 bytes

NβF³«F⁻β‹ι²« / \¶|   |¶ \ /Mײι↑¿⁻¹ιM⁶←

Try it online! Edit: Saved some bytes thanks to @ASCII-only (not sure exactly how many as I also saved another 6 10 bytes but then needed to spend 4 bytes on a bugfix). Now using nested loops, which is what this should have been all along.

\$\endgroup\$
7
  • \$\begingroup\$ 45 bytes: A / \¶| |¶ \ /αNβFβ«α←←»Fβ«α↖↖M⁶←»Fβ«αM⁴↑←← (btw charcoal autocompletes any needed » at the end) \$\endgroup\$
    – ASCII-only
    May 2, 2017 at 23:00
  • \$\begingroup\$ @ASCII-only Sadly I can't seem to find the Charcoal documentation any more, so I have no idea what your code does. \$\endgroup\$
    – Neil
    May 3, 2017 at 9:37
  • \$\begingroup\$ commands are on the wiki here, basically Assign(hexagon_with_space_to_left, a);InputNumber(b);for(b){Print(a);Move(:Left);Move(:Left);}for(b){Print(a);Move(:UpLeft);Move(:UpLeft);Move(6, :Left);}for(b){Print(a);Move(4, :Up);Move(:Left);Move(:Left);}, each for loop draws one side \$\endgroup\$
    – ASCII-only
    May 3, 2017 at 9:40
  • \$\begingroup\$ So pretty much what you were you doing but with the string saved as a variable \$\endgroup\$
    – ASCII-only
    May 3, 2017 at 9:45
  • \$\begingroup\$ @ASCII-only By reversing the direction of drawing I was able to save a further 2 bytes. (Also I'm slightly disappointed that the best way of drawing the hexagon is a string literal, but at least this makes it easy to repeat.) \$\endgroup\$
    – Neil
    May 3, 2017 at 9:57
7
\$\begingroup\$

Python 2, 184 177 174 164 bytes

n=input();p='|   |';e=' \\ /'
for i in range(n):k=' '*(4*i-5);w='  '*~(i-n);print w+[' / \\'*-~i+'\n'+w+p[:4]*i+p,' /'+e+k[3:]+e+' \\\n'+w+p+k+p][2<i<n-1]
print e*n

Try it Online!

-7 bytes thanks to Ørjan Johansen

\$\endgroup\$
4
  • \$\begingroup\$ You are missing the rightmost |s on the top three and the bottom hexagon row. \$\endgroup\$ Apr 24, 2017 at 0:00
  • \$\begingroup\$ p[:4]*(i+2) instead of p[:4]*(i+1) seems to fix it. \$\endgroup\$ Apr 24, 2017 at 0:10
  • \$\begingroup\$ You are only using b in one spot, so combining that with your ~ trick, w=' '*2*~(i-n) is 7 bytes shorter. \$\endgroup\$ Apr 24, 2017 at 0:25
  • \$\begingroup\$ @ØrjanJohansen Thanks, the code went through a lot of refactoring and i forgot to change those things \$\endgroup\$ Apr 24, 2017 at 0:28
6
\$\begingroup\$

JavaScript (ES6), 243 bytes

f=n=>(n=n*2-2,a=[...Array(n+3)].map(_=>Array(n*2+5).fill` `),g=(y,x)=>(a[y+1][x]=a[y+1][x+4]=`|`,a[y][x+1]=a[y+2][x+3]=`/`,a[y][x+3]=a[y+2][x+1]=`\\`),[...Array(n+!n)].map((_,i)=>i%2||(g(n,i*2),g(i,i=n-i),g(i,n+i))),a.map(a=>a.join``).join`
`)
<input type=number oninput=o.textContent=f(this.value)><pre id=o>

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 133 129 128 126 bytes

Builds the output character by character with two for loops.

n=>{for(s='',y=n*2,n*=4;~y--;s+=`
`)for(x=n;~x--;)s+=' \\ /|'[x>y-2&x<n-y&(k=x+y&3,x>n-y-6|x<y+4|y<2)?y&1?k:k+1&4:0];return s}

How it works

In the outer loop, y iterates from n*2-1 to -1. In the inner loop, x iterates from n*4-1 to -1. We set k = (x+y) & 3, which is the underlying pattern that is used to generate the hexagons.

Below is the resulting grid for n = 4:

     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 -1
   +---------------------------------------------------
 7 |  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2
 6 |  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1
 5 |  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0
 4 |  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3
 3 |  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2
 2 |  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1
 1 |  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0
 0 |  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3
-1 |  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2

On even rows, a cell is filled with a pipe character when k = 3, and a space otherwise. The pipe is the 5th character in our reference string " \ /|", so the correct index is given by (k+1) & 4.

On odd rows, each cell is filled directly with the corresponding character in the reference string:

  • k = 0 → space
  • k = 1 → "\"
  • k = 2 → space
  • k = 3 → "/"

Below is our updated example (spaces replaced with dots):

     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 -1
   +---------------------------------------------------
 7 |  .  \  .  /  .  \  .  /  .  \  .  /  .  \  .  /  .
 6 |  .  .  |  .  .  .  |  .  .  .  |  .  .  .  |  .  .
 5 |  .  /  .  \  .  /  .  \  .  /  .  \  .  /  .  \  .
 4 |  |  .  .  .  |  .  .  .  |  .  .  .  |  .  .  .  |
 3 |  .  \  .  /  .  \  .  /  .  \  .  /  .  \  .  /  .
 2 |  .  .  |  .  .  .  |  .  .  .  |  .  .  .  |  .  .
 1 |  .  /  .  \  .  /  .  \  .  /  .  \  .  /  .  \  .
 0 |  |  .  .  .  |  .  .  .  |  .  .  .  |  .  .  .  |
-1 |  .  \  .  /  .  \  .  /  .  \  .  /  .  \  .  /  .

In the following formulas, we define N = n*4 for readability (although the same variable is used in the code).

The triangle shape is obtained by testing:

  • x > y - 2 → removes the right corner
  • AND x < N - y → removes the left corner

And the inner part is removed by testing:

  • x > N - y - 6 → keeps only the left edge
  • OR x < y + 4 → keeps only the right edge
  • OR y < 2 → keeps only the bottom edge

Demo

let f =

n=>{for(s='',y=n*2,n*=4;~y--;s+=`
`)for(x=n;~x--;)s+=' \\ /|'[x>y-2&x<n-y&(k=x+y&3,x>n-y-6|x<y+4|y<2)?y&1?k:k+1&4:0];return s}

console.log(f(3))
console.log(f(4))
console.log(f(5))
console.log(f(6))
console.log(f(7))

\$\endgroup\$
3
  • \$\begingroup\$ Does [x>y-2&x<n-y&(x>n-y-6|x<y+4|y<2)&&y&1?x+y&3:x-~y&4] work? \$\endgroup\$
    – Neil
    Apr 26, 2017 at 16:01
  • \$\begingroup\$ @Neil Hmm, I don't think so. We'd need parenthesis around the ternary expression and (x+y+1)&4 is not the same as (((x+y)&3)+1)&4. \$\endgroup\$
    – Arnauld
    Apr 26, 2017 at 16:16
  • \$\begingroup\$ No, of course it isn't. What was I thinking... \$\endgroup\$
    – Neil
    Apr 26, 2017 at 16:30
3
\$\begingroup\$

Jelly,  62  61 bytes

Currently containing six sixes.

_‘<×⁸>6
Rµ‘⁾| ẋ⁾/\ẋ⁸¤ż;/K€µ⁶ðMṀ_6r6ẋð¦"Jç¥
ḤḶUẋ@€⁶;"ǵ-ịṙ6ṭ⁸Y

Try it online!

How?

_‘<×⁸>6 - Link 1, should we eat the praline? row number, triangle size
_       - row number minus triangle size
 ‘      - plus one
  <     - less than triangle size? (1 if one of the last rows else 0)
   ×⁸   - multiply by row number   (row number or 0)
     >6 - greater than 6?          (row number if between row 6 and last two rows)

Rµ‘⁾| ẋ⁾/\ẋ⁸¤ż;/K€µ⁶ðMṀ_6r6ẋð¦"Jç¥ - Link 2, build a solid triangle: triangle size
                                              (except the very bottom row)
R                                  - range: [1,2,...,size]
 µ                                 - monadic chain separation, call that r
  ‘                                - increment: [2,3,...,size+1]
   ⁾| <space                       - literal "| "
      ẋ                            - repeat: ["| | ","| | | ",...]
            ¤                      - nilad followed by link(s) as a nilad:
       ⁾/\                         -   literal "/\"
           ⁸                       -   link's left argument, r
          ẋ                        -   repeat (vectorises): ["/\","/\/\",...]
             ż                     - zip the two repeated lists together: [["/\","| | "],["/\/\","| | | "],...]
              ;/                   - reduce by concatenation: ["/\","| | ","/\/\","| | | ",...]
                K€                 - join with spaces for €ach: ["/ \","|   |  ","/ \ / \","|   |   |  ",...]
                  µ                - monadic chain separation call that s
                                 ¥ - last two links a a dyad:
                               J   -   range(length(s))  
                                ç  -   call the last (1) link as a dyad (left = result of J, right = size)
                              "    - zip with: (call those d)
                    ð       ð¦     -   apply to indexes:
                   ⁶               -   a literal space character
                     M             -     indexes of maximal elements in an element of s (a row)
                      Ṁ            -     maximum (this is the rightmost non-space index, MṀ working like length ignoring trailing spaces)
                       _6          -     subtract 6  (6 indexes back from the right)
                         r6        -     range from there to 6, i.e [l-6,l-7,...,6]
                           ẋ       -     repeat d times (1 or 0), thus applying to the middle rows but not the bottom and top ones.

ḤḶUẋ@€⁶;"ǵ-ịṙ6ṭ⁸Y - Main link: triangle size
Ḥ                  - double(size)
 Ḷ                 - unlength: [0,1,2,...,double(size)-1]
  U                - upend: [double(size)-1,...,2,1,0]
      ⁶            - literal space character
   ẋ@€             - repeat for €ach with reversed arguments ["  ...  ",...,"  "," ",""]
         Ç         - call the last link (2) as a monad(size)
       ;"          - zip with concatenation (zips the leading spaces with the solid triangle body)
          µ        - monadic chain separation, call that t
           -ị      - index -1 (last but one row of t)
             ṙ6    - rotate left by 6 (any number congruent to 2 mod 4 would do)
               ṭ⁸  - tack to t (add this new row on)
                 Y - join all the rows by new lines
                   - implicit print
\$\endgroup\$
2
  • \$\begingroup\$ There is a Missing > in the explanation (<space) \$\endgroup\$ Apr 24, 2017 at 17:45
  • \$\begingroup\$ @RomanGräf thanks I edited the explanation! If you just meant more than "the under the space in the explanation is misaligned", let me know. \$\endgroup\$ Apr 24, 2017 at 21:36
1
\$\begingroup\$

Pyth, 82 bytes

jb+Rt_.rd"/\\"_.e<s[dd*dkb*dyQ)hyQ*,"|   |""/ \\ /"tQ*Q" / \\"+*Q"|   "\|*Q" \\ /"

Try it online!

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

Mathematica, 155 bytes

""<>Table[If[i+j<d||i-j>d+1||i+j>d+5&&i-j<d-3&&j<d-1," ",Switch[Mod[i+d+{j,-j},4],{1,3},"/",{3,1},"\\",{1,1},"|",_," "]],{j,(d=2#)+1},{i,4#+1}]~Riffle~"\n"&

with \n replaced with a newline.

More readable:

"" <> Table[
    If[i+j < d || i-j > d+1 || 
      i+j > d+5 && i-j < d-3 && j < d-1, " ", 
     Switch[Mod[i+d+{j,-j}, 4], {1, 3}, "/", {3, 1}, 
      "\\", {1, 1}, "|", _, " "]], {j, (d=2#)+1}, {i, 4#+1}]~
   Riffle~"\n" &

Creates an array of characters, indexed by i from 1 to 4 n + 1 horizontally and j from 1 to 2 n + 1 vertically. First, Switch[Mod[i+d+{j,-j},4],{1,3},"/",{3,1},"\\",{1,1},"|",_," "] fills in a hexagonal grid:

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

then If[i+j<d||i-j>d+1||i+j>d+5&&i-j<d-3&&j<d-1," ",...] replaces this with " " outside the unfilled triangle.

\$\endgroup\$

Your Answer

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

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