Hexagonal Triangles!

20

1

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:
           / \
          |   |
         / \ / \
        |   |   |
       / \ / \ / \
      |   |   |   |
     / \ /     \ / \
    |   |       |   |
   / \ /         \ / \
  |   |           |   |
 / \ / \ / \ / \ / \ / \
|   |   |   |   |   |   |
 \ / \ / \ / \ / \ / \ /

Comrade SparklePony

Posted 2017-04-23T19:53:20.857

Reputation: 5 784

22If there isn't a Hexagony answer for this, I will lose all faith in @MartinEnder. – caird coinheringaahing – 2017-04-23T20:00:16.047

@Soyoucanreplytomeincomments Let's just say if I could folow users on here, they'd be on the list. – phyrfox – 2017-04-23T20:04:48.710

1

@phyrfox You can, sort of.

– Dennis – 2017-04-23T21:19:24.223

2I 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. – Neil – 2017-04-23T21:20:15.017

3@Neil you are forgiven for not learning an entirely new programming language. But that's your first warning! – caird coinheringaahing – 2017-04-23T21:58:28.907

Is any amount of trailing whitespace allowed on each line? – math junkie – 2017-04-23T22:51:01.960

@mathjunkie trailing whitespace is fine. – Comrade SparklePony – 2017-04-23T22:51:51.190

@Soyoucanreplytomeincomments No pressure or anything... – Martin Ender – 2017-04-24T18:22:06.613

Answers

11

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.

Neil

Posted 2017-04-23T19:53:20.857

Reputation: 95 035

45 bytes: A / \¶| |¶ \ /αNβFβ«α←←»Fβ«α↖↖M⁶←»Fβ«αM⁴↑←← (btw charcoal autocompletes any needed » at the end) – ASCII-only – 2017-05-02T23:00:22.140

@ASCII-only Sadly I can't seem to find the Charcoal documentation any more, so I have no idea what your code does. – Neil – 2017-05-03T09:37:24.717

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

– ASCII-only – 2017-05-03T09:40:18.737

So pretty much what you were you doing but with the string saved as a variable – ASCII-only – 2017-05-03T09:45:17.510

@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.) – Neil – 2017-05-03T09:57:31.967

(I guess you can repeat something more complicated using V, if only I knew how to get it into a string in the first place...) – Neil – 2017-05-03T10:07:10.693

Let us continue this discussion in chat.

– ASCII-only – 2017-05-03T10:24:28.603

7

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

math junkie

Posted 2017-04-23T19:53:20.857

Reputation: 2 490

You are missing the rightmost |s on the top three and the bottom hexagon row. – Ørjan Johansen – 2017-04-24T00:00:34.820

p[:4]*(i+2) instead of p[:4]*(i+1) seems to fix it. – Ørjan Johansen – 2017-04-24T00:10:23.277

You are only using b in one spot, so combining that with your ~ trick, w=' '*2*~(i-n) is 7 bytes shorter. – Ørjan Johansen – 2017-04-24T00:25:37.800

@ØrjanJohansen Thanks, the code went through a lot of refactoring and i forgot to change those things – math junkie – 2017-04-24T00:28:17.943

6

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>

Neil

Posted 2017-04-23T19:53:20.857

Reputation: 95 035

4

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))

Arnauld

Posted 2017-04-23T19:53:20.857

Reputation: 111 334

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? – Neil – 2017-04-26T16:01:04.170

@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. – Arnauld – 2017-04-26T16:16:00.597

No, of course it isn't. What was I thinking... – Neil – 2017-04-26T16:30:22.947

3

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

Jonathan Allan

Posted 2017-04-23T19:53:20.857

Reputation: 67 804

There is a Missing > in the explanation (<space) – Roman Gräf – 2017-04-24T17:45:36.770

@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. – Jonathan Allan – 2017-04-24T21:36:41.770

1

Pyth, 82 bytes

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

Try it online!

Leaky Nun

Posted 2017-04-23T19:53:20.857

Reputation: 45 011

1

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.

Not a tree

Posted 2017-04-23T19:53:20.857

Reputation: 3 106