| Bytes | Lang | Time | Link |
|---|---|---|---|
| 141 | Julia 1.0 | 240914T000010Z | Ashlin H |
| nan | Vyxal j | 240913T124037Z | pacman25 |
| 177 | JavaScript Node.js | 210602T141044Z | user1006 |
| 060 | Vyxal | 210602T084218Z | emanresu |
| 150 | SlimSharp | 210217T155724Z | Joel Coe |
| 009 | Canvas | 210106T090113Z | Razetime |
| 120 | Haskell | 210110T110226Z | AZTECCO |
| 100 | Haskell | 210110T175809Z | xnor |
| 174 | Python 3.8 prerelease | 210106T102551Z | Anakhand |
| 5047 | J | 210106T182624Z | xash |
| 150 | Haskell | 210108T165621Z | Wheat Wi |
| 109 | C gcc | 210107T085008Z | AZTECCO |
| 025 | 05AB1E | 210106T221241Z | ovs |
| 168 | Haskell | 210107T053100Z | Steven F |
| 144 | C gcc | 210106T141811Z | Noodle9 |
| 107 | JavaScript ES6 | 210106T202703Z | Arnauld |
| 102 | Perl 5 p | 210106T202215Z | Nahuel F |
| 143 | Perl 5 | 210106T175444Z | Kjetil S |
| 070 | 05AB1E | 210106T174512Z | Makonede |
| 114 | Python 2 | 210106T093232Z | ovs |
| 092 | Python 2 | 210106T101610Z | xnor |
| 094 | Retina 0.8.2 | 210106T100812Z | Neil |
| 141 | Ruby | 210106T081511Z | vrintle |
| 014 | Charcoal | 210106T085419Z | Razetime |
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])
There's nothing too special about the algorithm, which is just a direct approach. A few techniques are worth mentioning:
- When saving the output characters to variables,
Char[32 47 92 95]saves some bytes over[' ' '/' '\\' '_']. - I used array comprehension to generate most of the lines, and the splat operator
...to unpack the results. - Julia strings use
*for concatenation and^for repitition. Implicit multiplication has a high precedence, so coefficients can be pulled out of an exponent. In this case,' '^(2n+2x-2)can be shortened to' '^2(n+x-1)
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"
])
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)))))
Vyxal j, 321 bitsv2, 40.125 bytes
ʁṘvI\/+?₌I‡\_*+p?dðø↲øM:ṘṪṫøSð\_Ŀ?‹IpJ‛\/‛/\vĿJ
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`
`
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.
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);
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*⁸/∔╬
-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=' ']
saved 9 thanks to @Wheat Wizard and @xnor.
Check @xnor answer and its big improvement on the approach to the problem (avoiding modulo and parallel lines) !
Equivalent of my C answer
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=' ']
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")
-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$~<:,])@+:
((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
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);}
- saved 2 thanks to @ceilingcat
The table below is not updated so values can differ, but the concept is:
- we have 2 pairs of parallel lines
. .
_______.______.________
| / \ | .
. | / \ | .
.| / \ |.
|/ \|
|\ /|.
.| \ / | .
. | \ / |
__|___\________/___|___
| . .
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
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]
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;}
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)
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--$_}{
-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}
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*>(£„._`:„/\‡,
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)
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
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)]}
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]}
Charcoal, 14 bytes
←×_θ↖θ→↗θ×_θ‖M
+1 byte fix from ASCII-Only.
Draws half of the hexagon, and mirrors it.