Draw Concentric ASCII Hexagons
Python - 251, 240, 239 228
l=input()+[0];m=max(l);A=abs;R=range
for j in R(2*m+1):print''.join([[' \\'[(A(j-i+m-1)/2.in l)*(2*m-i)/(j-m-.5)>1],'/'][(A(3*m-i-j)/2.in l)*(i-m-j+.5)/(j-.5-m)>0],'_'][(A(m-j)in l)*(A(2*m-i-.5)<A(m-j))]for i in R(4*m)).rstrip()
Alternative approach (251):
l=input()+[0]
l.sort()
m=max(l)
M=2*m
s=[[' ']*m*4for j in' '*(M+1)]
for i in l:
I=2*i;s[m-i][M-i:M+i]=s[m+i][M-i:M+i]='_'*I
for k in range(i):K=k+1;s[m-k][M-I+k]=s[m+K][M+I-K]='/';s[m-k][M+I-K]=s[m+K][M-I+k]='\\'
for t in s:print''.join(t).rstrip()
CJam, 148 116 109 bytes
This took a lot longer than I expected. Originally, I just wanted to iteratively build the upper left quadrant, as in the diamond challenges, and then get the rest from mirroring. But I didn't notice that the underscores don't obey mirror symmetry between the upper and lower half. So I had to redo most of that, to generate the right half iteratively and then only mirror once (to the left).
S]2[l~]:(f#:+2bW%{_,2/~:T;{IT):T1<'\'/?S?S++}%__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+}fI{)T)2*2$,-*1$W%"\/"_W%er@N}/
Test it here.
A Fibonacci-esque example:
8 3 1 5 2
________________
/ \
/ \
/ __________ \
/ / \ \
/ / ______ \ \
/ / / ____ \ \ \
/ / / / __ \ \ \ \
/ / / / / \ \ \ \ \
\ \ \ \ \__/ / / / /
\ \ \ \____/ / / /
\ \ \______/ / /
\ \ / /
\ \__________/ /
\ /
\ /
\________________/
Explanation:
As stated at the top, I start by building the right half iteratively. That is, initially I've got only a single space in the grid, and then for each possible ring, I either surround the existing grid in spaces or a new semi-hexagon.
Once that's done, I mirror each line to the left and pad it with leading spaces for correct alignment. Here is a breakdown of the code:
"Prepare the input and the grid:";
S]2[l~]:(f#:+2bW%
S] "Push string with a space and wrap it in an array. This is the grid.";
2 "Push a 2 for future use.";
[l~] "Read and evaluate the input, wrap it in an array.";
:( "Decrement each number by 1.";
f# "Map each number i to 2^i.";
:+ "Sum them all up.";
2b "Get the base two representation.";
W% "Reverse the array.":
"At this point, the stack has the proto-grid at the bottom, and an array of 1s and
0s on top, which indicates for each hexagon if it's present or not.";
"Next is a for loop, which runs the block for each of those 0s and 1s, storing the
actual value in I. This block adds the next semi-hexagon or spaces.";
{ ... }fI
"First, append two characters to all existing lines:";
_,2/~:T;{IT):T1<'\'/?S?S++}%
_ "Duplicate the previous grid.";
,2/ "Get its length, integer-divide by 2.";
~:T; "Get the bitwise complement and store it in T. Discard it.";
{ }% "Map this block onto each line of the grid.";
I "Push the current hexagon flag for future use.";
T):T "Push T, increment, store the new value.";
1<'\'/? "If T is less than 1, push \, else push /.";
S? "If the current flag is 0, replace by a space.";
S++ "Append a space and add it to the current line.";
"So for hexagons this appends '\ ' to the top half and '/ ' to the bottom half.
For empty rings, it appends ' ' to all lines.";
"Now add a new line to the top and the bottom:"
__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+
__ "Get two copies of the grid.";
,2/ "Get its length, integer-divide by 2.";
= "Get that line - this is always the middle line.";
,2/ "Get ITS length, integer'divide by 2.";
I'_S?* "Get a string of that many _ or spaces depending on the
current flag.";
_S+ "Duplicate and a space.";
a@+ "Wrap in an array, pull up the grid, and prepend the line.";
\ "Swap with the other copy.";
I'/S? "Choose between / and a space depending on the flag.";
S++ "Append a space, and add both characters to the line.";
a+ "Wrap in an array, and append line to the grid.";
"This is all. Rinse and repeat for all rings. The result will look something like this:
_____
\
___ \
__ \ \
_ \ \ \
\ \ \ \
_/ / / /
__/ / /
___/ /
/
_____/
Note that there are still trailing spaces.";
"Finish up all lines. These will not be joined together any more, but simply left
on the stack in pieces to printed out back-to-back at the end of the program.
The following runs the given block for each line:";
{ ... } /
"This generates the necessary indentation, then mirrors the lines and puts them
in the right order:"
)T)2*2$,-*\_W%"\/"_W%er\N
) "Slice off that trailing space, but leave it on the stack.";
T "Remember T? That still has something like the the size of
the grid from the last iteration. In fact it's N-1, where
N is the largest visible hexagon. We can use that to figure
out how many spaces we need.";
)2* "Increment and double.";
2$ "Copy the current line.";
,- "Subtract its length from 2*N.";
* "Repeat the space that often. This is our indentation.";
\_ "Swap with the line and duplicate.";
W% "Reverse the line.";
"\/"_W%er "Replace slashes with backslashes and vice versa.";
\ "Swap with the original line.";
N "Push a line break.";
APL (222 bytes in UTF-8)
(and 133 chars)
Since this question specifically asks for amount of bytes in UTF8 representation, I had to actually ungolf it a bit so that it is longer but its UTF8 representation is shorter. (In particular, the commute operator's character ⍨
is three bytes while ()
is only two, so that optimalisation doesn't work anymore, and it also makes assignment very expensive.)
{⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]
Previous version, which is shorter in characters (124) but uses more bytes when represented in UTF-8 (230, which would put it in second place):
M←' '⋄{⎕←⍵/⍨~⌽∧\⌽⍵=M}¨↓⊃{⍵{⍺=M:⍵⋄⍺}¨K↑⍺↑⍨-.5×(K←⍴⍵)+⍴⍺}/{Z⍪⊖⌽Z←↑(⊂(⍵/M),'-'/⍨2×⍵),⍵{('/'↑⍨-⍵),'\',⍨M/⍨2 4-.×⍵⍺}¨⌽⍳⍵}¨N[⍋N←,⎕]
Test:
{⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]
⎕:
3 1 5 2
----------
/ \
/ ------ \
/ / ---- \ \
/ / / -- \ \ \
/ / / / \ \ \ \
\ \ \ \ / / / /
\ \ \ -- / / /
\ \ ---- / /
\ ------ /
\ /
----------