g | x | w | all
Bytes Lang Time Link
141Julia 1.0240914T000010ZAshlin H
nanVyxal j240913T124037Zpacman25
177JavaScript Node.js210602T141044Zuser1006
060Vyxal210602T084218Zemanresu
150SlimSharp210217T155724ZJoel Coe
009Canvas210106T090113ZRazetime
120Haskell210110T110226ZAZTECCO
100Haskell210110T175809Zxnor
174Python 3.8 prerelease210106T102551ZAnakhand
5047J210106T182624Zxash
150Haskell210108T165621ZWheat Wi
109C gcc210107T085008ZAZTECCO
02505AB1E210106T221241Zovs
168Haskell210107T053100ZSteven F
144C gcc210106T141811ZNoodle9
107JavaScript ES6210106T202703ZArnauld
102Perl 5 p210106T202215ZNahuel F
143Perl 5210106T175444ZKjetil S
07005AB1E210106T174512ZMakonede
114Python 2210106T093232Zovs
092Python 2210106T101610Zxnor
094Retina 0.8.2210106T100812ZNeil
141Ruby210106T081511Zvrintle
014Charcoal210106T085419ZRazetime

Julia 1.0, 141 bytes

b,c,d,e=Char[32 47 92 95]
!n=println.([b^n*e^2n,[b^(n-x)*c*b^2(n+x-1)*d for x=1:n]...,[b^x*d*b^2(2n-x-1)*c for x=0:n-2]...,b^(n-1)*d*e^2n*c])

Try it online!

There's nothing too special about the algorithm, which is just a direct approach. A few techniques are worth mentioning:

Ungolfed version:

f(n)=print.([
	' '^n * '_'^2n*'\n',
	[' '^(n-x) * '/' * ' '^(2n+2x-2) * "\\\n" for x=1:n]...,
	[' '^(x-1) * '\\' * ' '^(4n-2x) * "/\n" for x=1:n-1]...,
	' '^(n-1) * '\\' * '_'^(2n) * "/\n"
])

Try it online!

I also tried building the output from arrays, but I couldn't beat the direct approach:

Julia, 196 bytes

using LinearAlgebra
!x=zeros(Int,x)'
~n=(A=I(n);M=15rotr90(A);Z(x)=zeros(Int,(x,2n));W=[Z(n-1);repeat([63],2n)'];X=[!n 63ones(Int,2n)' !n;M Z(n) 60A;60A W M];@.println(join($eachrow(Char(X+32)))))

Attempt This Online!

Vyxal j, 321 bitsv2, 40.125 bytes

ʁṘvI\/+?₌I‡\_*+p?dðø↲øM:ṘṪṫøSð\_Ŀ?‹IpJ‛\/‛/\vĿJ

Try it Online!

Bitstring:

000111011001101110101111110110111001100001100001010000100001011011101101110111011111010011111000100011010001001101101111101010101010100000010010101111001011110101111111100110100110011001100010000010111110100011011001101101111001100001000100100010111001001100101111110100110110011111000001001100000101101000000011101101110

uses new palindrome stuff plus j flag

JavaScript (Node.js), 177 bytes

n=>[...Array((N=2*n)+1)].map((_,i,a,g=i>n,s=g?i-n-1:n-i,j=i&&N-i,r='_'.repeat(N),S=Z=>' '.repeat(Z))=>i?S(s)+'/\\'[+g]+(j?'':r)+S(g?j&&6*n-2*i:N+2*--i)+'\\/'[+g]:S(n)+r).join`
`

Try it online!

Not the shortest but uses a different approach. Second in my series of text-writing programs which aren't the shortest, but help assemble a repertoire of array solutions.

Vyxal, 60 bytes

ð*\_?*d+,(n-‹ð*\/n?+ð*d++\\+,)(nð*\\?d‹n-n›?=[\_|ð]*d++\/+,)

Try it Online!

SlimSharp, 150 bytes

I n=RI(),m=n;S b=new S('-',n*2).Pad(n*-3),l="/",r="\\";Action<I> x=a=>P(l.Pad(-a).Pad(4*n-a)+r);P(b);for(;m>0;)x(m--);l=r;r="/";for(;m<n;)x(++m);P(b);

https://dotnetfiddle.net/iXLzcO

The fiddle differs slightly from the post because .Net Fiddle can't use the RI() function to read from the console.

This is still the naiive version, without any recursive or coordinate mapping tricks. I'm unlikely to get shorter, because SlimSharp hasn't defined shortcuts for some of the relevant array and string functions yet.


C#, 227 bytes

The full C# looks like this, and that's still assuming all the necessary using directives and that we get to abstract to a method.

void H(int n){int m=n;string b=new string('-',n*2).PadLeft(n*3),l="/",r="\\";Action<int> x=a=>Console.WriteLine(l.PadLeft(a).PadRight(4*n-a)+r);Console.WriteLine(b);for(;m>0;)x(m--);l=r;r="/";for(;m<n;)x(++m);Console.Write(b);}

Canvas, 15 9 bytes

 _;1*⁸/∔╬

Try it here!, another 9 bytes

-6 bytes after fixing the program.

Draws a quarter of the hexagon, and quad palindromizes.

Haskell, 129 120 bytes

g=mod
f n|a<-n*4=[c|y<-[-n..n],x<-[0..a],let c|x<1='\n'|g x(n*3+1)>n,abs y==n='_'|g(x+y)a==1='/'|g(x-y)a<1='\\'|1>0=' ']

Try it online!

We make cartesian coordinates using list comprehension |y<-[0..n*2],x<-[0..a]

[c| ... ,let c| ... | ... | ... ] and we yeld the character needed based on x-y or x+y to draw lines..
We use modulo to draw multiple lines(2)
Special case is for _ which doesn't need a x/y ratio but a range, we used modulo to do just one comparison > instead of an a>x>b like

Haskell, 100 bytes

f n=unlines[q<$>[1..3*n]++[1-n..0]|y<-[-n..n],let q x|abs y==n,x>n='_'|x==y='\\'|x+y==1='/'|1>0=' ']

Try it online!

Golfing AZTECCO's answer plus some new techniques.

The main idea is that the hexagon is simpler if we transplant the first n columns to the end.

|-|
   ______   
  /      \  
 /        \ 
/          \
\          /
 \        / 
  \______/  

         |-|
______      
      \    /
       \  / 
        \/  
        /\  
       /  \  
______/    \

Now all the / and \ are in a single line, and the _ are all to the left of those. This makes it much easier to do AZTECCO's strategy of determining the character from the coordinate. To implement these relabeled coordinates, we replace the x-coordinates [1..4*n] with a cycled and shifted version [1..3*n]++[1-n..0].

Python 3.8 (pre-release), 174 bytes

n=int(input())
b,a,s="\/ "
z,f=range(n),lambda c,d,t:((n-1-i)*s+c+2*(n+i)*s+d for i in t)
print(f"{'_'*2*n:^{4*n}}",*f(a,b,z),*f(b,a,z[:0:-1]),f"{b:>{n}}{'_'*2*n}/",sep="\n")

Try it online!

-1 byte thanks to @Duncan

-8 bytes thanks to @Danis

J, 50 47 bytes

-3 thanks to Jonah!

' \/_'{~]|."1((0,]+2*|.)@=@i.,.3,3,~0$~<:,])@+:

Try it online!

((0,]+2*|.)@=@i.  ,.  3,3,~0$~<:,])@+:
     0 0 0 0            3 3 3 3
     1 0 0 2            0 0 0 0
     0 1 2 0            0 0 0 0
     0 2 1 0            0 0 0 0
     2 0 0 1            3 3 3 3

    ]|."1
0 0 3 3 3 3 0 0
0 2 0 0 0 0 1 0
2 0 0 0 0 0 0 1
1 0 0 0 0 0 0 2
0 1 3 3 3 3 2 0

' \/_'{~ 
  ____
 /    \    
/      \    
\      /  
 \____/  

Haskell, 150 bytes

r=reverse
m(o:c:k)=o:c:c:c:k++" "
f 1=[["\\  /","__ "],["/__\\"]]
f n|[w:i,j]<-map m<$>f(n-1),_:_:k<-r$m w=[r k:w:i,k:j]
h[i,j]=unlines$r<$>r i++j
h.f

Try it online!

A more recursive version of this answer. The arbitrariness of this challenge makes this pretty frustrating.

Explanation

This answer is a bit hard to explain. The challenge is, as I already said, arbitrary in a few ways, so the code is sort of just a nest of symbols.

Idea

The idea of the program here is to build up the two halves. That is when calculating the nth hexagon we get the two halves for the n-1th hexagon and use that to make the next biggest one.

There are some caveats though. We build the top half up-side-down and we build both halves mirrored left to right. We do this because it is convenient to do it this way. No deep reason it just makes things shorter even if it does make things a little incomprehensible.

Details

The first line is pretty straight forward r is an alias for reverse. The second line is not so straight forward. m is a nonsense function, it exists because it or a similar operation needs to be done in a few places. It doesn't really have a semantic meaning. The best explanation of what it does here is the code.

m(o:c:k)=o:c:c:c:k++" "

From here we start getting to f which handles basically all of the logic. The first case for f is the base case, it is pretty standard

f 1=[["\\  /","__ "],["/__\\"]]

Note that we return a list of two items instead of a tuple. In any sane program we would be using a tuple since it is fixed at 2 elements. However later we will map over both arguments of this with the same function. It is hard to do that with a tuple but easy with a list, and the list doesn't pose any drawbacks so we use it.

Then we have the inductive case. First we fetch the previous case, and double map our m over it. This makes the hexagon 1 unit wider (2 characters) and moves it half a unit (1 character) to the right (although since this whole thing is backwards the space characters are added on the right). We pattern match this to [w:i,j] because we want to use w to make new rows later. Speaking of which next we make the rows. We do this with a pattern match:

_:_:k<-r$m w

This is sort of nonsense code. It just slaps together things we already had to produce the correct output. k and its reverse form the new rows so we add them in. and return that.

After f we have h which turns the output of f into a string. It undoes all the wacky transforms we used during the construction and packages it up to be used.

With all that we just compose f and h for the final function.

C (gcc), 119 109 bytes

a,i,j;f(n){for(i=a+=a=j=n*2;~j;)putchar(!i--?i=a,j--,13:i%(n*3)<n|j%(n*2)?(i-~j-n)%a?(i-j+n)%a?32:92:47:95);}

Try it online!

The table below is not updated so values can differ, but the concept is:

        .    .
_______.______.________   
  |   /        \   |  .
. |  /          \  | .
 .| /            \ |.
  |/              \|
  |\              /|.
 .| \            / | .
. |  \          /  |
__|___\________/___|___   
  |    .      .

we iterate x,y from size to 0 and we sum them to check if a / should be printed, we subtract to check for \ , we use modulo to check both parallels.

    i 65432109876543210. j
 i+j-n    ________      8 
13+7-4=> /        \     7 
14+6-4  /          \    6 
15+5-4 /            \   5 
      /              \  4 
      \     1+3-4=>  /  3
       \    2+2-4   /   2
        \   3+1-4  /    1
         \________/     0

05AB1E, 33 29 25 bytes

-4 (7) bytes thanks to Kevin Cruijssen!

L+<'/úíºI·'_ך»∊¶¡`ðs‡).c

Try it online!

05AB1E has a canvas builtin which might be useful, but is quite tricky to get working, this is just the mirror builtins º and and the centralize builtin .c.

Haskell, 186 168 bytes

-18 bytes with xnor's fixes and removing unneeded spaces on the last line

s=' '
(!)=replicate
e=reverse
h n=unlines$(\m->(n!s++(2*n)!'_'++n!s):e(e<$>m)++init m++[(n-1)!s++'\\':(2*n)!'_'++"/"])$(\i->i!s++'\\':(4*n-2*i-2)!s++'/':i!s)<$>[0..n-1]

Try it online!

Ungolfed:

hex :: Int -> String
hex n = unlines $ first: middle ++ (init $ reverse (map reverse middle)) ++ [last]
  where
    first = replicate n ' ' ++ replicate (2*n) '_' ++ replicate n ' '
    f i = replicate i ' ' ++ "/" ++ replicate (n-i + 2*n + n-i -2) ' ' ++ "\\" ++ replicate i ' '
    middle = map f [n-1,n-2..0]
    last = replicate (n-1) ' ' ++ "\\" ++ replicate (2*n) '_' ++ "/" ++ replicate (n-2) ' '

C (gcc), 194 \$\cdots\$ 149 144 bytes

Saved 13 14 19 bytes thanks to ceilingcat!!!

p(n,c){for(;n--;)printf(L"/\\ _\n"+c);}i;t;f(n){p(n,2);for(i=t=p(2*n,3);i>=p(1,4);t=i/n?--i,1:t)i+=!p(!p(n+i<<!p(!p(n+~i,2),t),t&!i|2),!t)-2*t;}

Try it online!

Explanation (before some golfs)

p(n,c){for(;n--;)                     // Helper function to print  
         putchar("/\\ _\n"[c]);}      //  one of '/', '\', ' ', '_' , or  
                                      //  newline n times, this function  
                                      //  also returns 0 
i;t;f(n){                             // Main function prints an n hexagon  
        p(n,2);                       // Print n leading spaces for the 1st  
                                      //  line 
        for(                          // Main loop
            i=t=p(2*n,3);             // Set i and t to 0,  
                                      //  and print 2*n '_'s for the 1st line
            i>=p(1,4);                // Loop until i goes below 0, and 
                                      //  print a newline
                                      // At the end of each loop:  
            i+=1-2*t,                 //  increment i for the 1st half  
                                      //   and then decrement i in the 2nd  
            t=i/n?--i,1:t)            //  keep t as t unless i equals n,   
                                      //  then make t 1 and decrement i   
                                      // In the main loop:
                p(n+~i,2),            //  print n-i-1 leading spaces     
                p(1,t),               //  print a '/' in the 1st half and a  
                                      //   '\' in the 2nd    
                p(n+i<<1,t&!i|2),     //  print the 2*(n+i) middle spaces  
                                      //   unless at the bottom print '_'s  
                p(1,!t);              //  print a '\' in the 1st half and a  
                                      //   '/' in the 2nd    
   }  
 

JavaScript (ES6),  109  107 bytes

w=>(x=0,W=w*4,i=g=y=>~y?`
 /\\_`[x++-W?y*!i|w/x|x>w*3?(x+~y+w)%W?(x+y)%W-w?1:3:2:4:x=i=0&y--]+g(y):'')(w*2)

Try it online!

Commented

w => (                        // w = input
  x = 0,                      // initialize x to 0
  W = w * 4,                  // W = total width
  i =                         // initialize i to a non-zero value
  g = y =>                    // g is a recursive function taking y
  ~y ?                        //   if y is not equal to -1:
    `\n /\\_`[                //     list of characters
      x++ - W ?               //     if this is not the end of the row:
        y * !i |              //       if this is neither the first nor the last row
        w / x |               //       or x is less than or equal to w
        x > w * 3 ?           //       or x is greater than w * 3:
          (x + ~y + w) % W ?  //         if (x - y - 1 + w) mod W is not equal to 0:
            (x + y) % W - w ? //           if (x + y) mod W is not equal to w:
              1               //             draw a space
            :                 //           else:
              3               //             draw a '\'
          :                   //         else:
            2                 //           draw a '/'
        :                     //       else:
          4                   //         draw a '_'
      :                       //     else:
        x = i = 0 & y--       //       decrement y, set x and i to 0 and draw a linefeed
    ] + g(y)                  //     append the result of a recursive call
  :                           //   else:
    ''                        //     stop the recursion
)(w * 2)                      // initial call to g with y = w * 2

Perl 5 (-p), 102 bytes

s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$&  /gm,s-( +)\\ 
-$&/ $1 \\
\\ $1 /
- for($\=' __ 
/  \
\__/')x--$_}{

Try it online!

-p and }{ at the end is a trick to only print the output record separator $\ at the end. It only works for one input record; the header is used to print all in one tio link.

$\=' __ 
/  \
\__/'   # output record separator initialized with hexagon (size 1)

s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$&  /gm,s-( +)\\ 
-$&/ $1 \\
\\ $1 /
- # regexes to increase the hexagon by 1

for .. --$_ # to repeat n-1 times where n is the input

Perl 5, 143 bytes

sub f{$n=pop;@b=map{join'',$"x($n-$_),'/','  'x($n+$_-1),'\\',$/}1..$n;join('',$"x$n,$u=__ x$n,$/,@b,map y|/\\|\\/|r,reverse@b)=~s| +/$|$u/|sr}

Try it online!

sub f{
  $n=pop;             #n = input
  @b=map{             #set array @b to line 2 - n+1
    join'',           #join parts into a line string
    $" x ($n-$_),     #space times n-1
    '/',              #char /
    '  ' x ($n+$_-1), #space times n+iterator minus 1
    '\\',             #char \
    $/                #char newline
  } 1..$n;            #n lines
  join('',            #return string of these joined:
    $" x $n,          #n spaces
    $u = __ x$n,      #n*2 underscores
    $/,               #char newline
    @b,               #lines 2 to n+1 constructed above
    map y|/\\|\\/|r,  #and bottom part which is the same
      reverse@b       #as top part reversed and /\ rotated
  )=~s| +/$|$u/|sr    #and change last spaces of last line to _'s
}

05AB1E, 70 bytes

ðש'_¹·×«©¶«©¹'/1Λ¹·Ì'.2Λ¹'\3.Λ«©„./`.;©¶¡Â‚€»`s'.ð:,¹3*>(£„._`:„/\‡,

Try it online!

Python 2, 119 114 bytes

i=n=input()
d=0
exec"k=i/n|d;print' '*i+'\_/'[~k]+'_ '[i-d<n]*2*(2*n+~i)+'\_/'[k]\nif i==d:d=i=-1\ni-=d|1;"*(n-~n)

Try it online!

Python 2, 92 bytes

k=n=input()
while 1:a=k^k>>n;print" "*a+"\/_"[k/n-2]+"_ "[-n<k<n]*2*(2*n+~a)+"\_/"[k/n];k-=1

Try it online!

Retina 0.8.2, 94 bytes

.+
$* ¶$&$* 
\G 
¶$%'/$`$%_$%_$`\
r` \G
$%`\$'$%_$%_$%'/¶
^¶( *)
$1 $.&$*_$.&$*_$&
T` `\_` +/$

Try it online! Link includes test cases. Explanation:

.+
$* ¶$&$* 

Insert two rows of n spaces.

\G 
¶$%'/$`$%_$%_$`\

Convert the first row into the top sides of the hexagon.

r` \G
$%`\$'$%_$%_$%'/¶

Convert the second row into the bottom sides of the hexagon.

^¶( *)
$1 $.&$*_$.&$*_$&

Insert the top line.

T` `\_` +/$

Replace the bottom line.

Ruby, 141 bytes

->(n,g=->c,d{(1..n).map{|i|" "*(n-i)+d+" "*2*(n+i-1)+c}},l=g[?/,e=?\\].reverse){[" "*n+?_*n*2,g[e,?/],l[0..-2],l[-1].sub(/ +(?=\/)/,?_*n*2)]}

Try it online!

If an upper underscore is allowed, then it would take a bit lesser bytes, while the hexagon is as pretty as it was earlier ;-)

Ruby, 114 bytes

->n{[" "*n+?_*2*n,(g=->c,d{(1..n).map{|i|" "*(n-i)+c+" "*2*(n+i-1)+d}})[?/,e=?\\],g[e,?/].reverse," "*n+?‾*n*2]}

Try it online!

Charcoal, 14 bytes

←×_θ↖θ→↗θ×_θ‖M

Try it online!

+1 byte fix from ASCII-Only.

Draws half of the hexagon, and mirrors it.