In my previous challenge, I drew the first diagram mostly by hand (with the help of vim's visual block mode). But surely there must be a better way...
Given an input of two dimensions, a width and a height, output a hexagonal grid with those dimensions in ASCII art.
Here's the diagram referenced in the intro (with minor edits), which should be
your output for the input width=7, height=3:
_____ _____ _____
/ \ / \ / \
_____/ -2,-1 \_____/ 0,-1 \_____/ 2,-1 \_____
/ \ / \ / \ / \
/ -3,-1 \_____/ -1,-1 \_____/ 1,-1 \_____/ 3,-1 \
\ / \ / \ / \ /
\_____/ -2,0 \_____/ 0,0 \_____/ 2,0 \_____/
/ \ / \ / \ / \
/ -3,0 \_____/ -1,0 \_____/ 1,0 \_____/ 3,0 \
\ / \ / \ / \ /
\_____/ -2,1 \_____/ 0,1 \_____/ 2,1 \_____/
/ \ / \ / \ / \
/ -3,1 \_____/ -1,1 \_____/ 1,1 \_____/ 3,1 \
\ / \ / \ / \ /
\_____/ \_____/ \_____/ \_____/
Notice several things:
The width and height are essentially equivalent to how many hexagons there are for a given y and x coordinate respectively. These will always be odd numbers.
Each hexagon is represented by the ASCII art
_____ / \ / \ \ / \_____/but borders are "shared" between neighboring hexagons.
The comma in the coordinates is always exactly two characters below the center of the top edge. The x-coordinate is then positioned directly before the comma, and the y-coordinate directly after.
You may assue that the coordinates will never be too large such that they would overlap the hexagon's borders.
Input may be taken as a whitespace-/comma-separated string, an array of integers, or two function/commandline arguments. Output must be a single string (to STDOUT, as a return value, etc.).
Since this is code-golf, the shortest code in bytes will win.
The grid above can be used as a test case. The maximum-sized
width=199, height=199 grid is obviously impractical to include here, but the
first few rows and columns should look like the following:
_____ ___
/ \ /
_____/-98,-99\_____/-96,
/ \ / \
/-99,-99\_____/-97,-99\___
\ / \ /
\_____/-98,-98\_____/-96,
/ \ / \
/-99,-98\_____/-97,-98\___
\ / \ /
\_____/-98,-97\_____/-96,
/ \ / \
/-99,-97\_____/-97,-97\___
\ / \ /
-
1\$\begingroup\$ Related \$\endgroup\$Alex A.– Alex A.2016年01月25日 22:04:26 +00:00Commented Jan 25, 2016 at 22:04
1 Answer 1
Ruby, 221 bytes
->w,h{s=' '
a=(s*9+?_*5)*(w/2)+$/
(2-h*2).upto(h*2+3){|y|c=y<4-h*2
a+=[b=c ?s:?\,円s+b,s,''][y%4]
(0-w/2).upto(w/2){|x|a+=["/#{h<y/2?s*7:"%3d,%-3d"}\\",s*7,?_*5,"/ \\"][(y+x*2+w)%4]%[x,y/4]}
a+='// '[c ?3:y%4]+$/}
a}
Ungolfed in test program
f=->w,h{
s=' ' #set s to space for golfing reasons
a=(s*9+?_*5)*(w/2)+$/ #start building the output with a row of just _ and space
(2-h*2).upto(h*2+3){|y| #iterate 4 times for each row of hexagons, plus an extra 2 at the end to finish last row
c=y<4-h*2 #condition for first two rows
a+=[b=c ?s:?\,円s+b,s,''][y%4] #string to be output before main set of hexagons (spaces for top row, \ for certain other rows
(0-w/2).upto(w/2){|x| #iterate through hexagons on each row, 4 lines for each with the following printf type string
a+=["/#{h<y/2?s*7:"%3d,%-3d"}\\",#line 1:contains ends / \ and numbers
s*7, #line 2 padding spaces
?_*5, #line 3 padding ___
"/ \\"][(y+x*2+w)%4]% #line 0 top of hexagon / \; formula to select string to be printed
[x,y/4] #numbers to be printed (if format for current line does not require them they are ignored)
}
a+='// '[c ?3:y%4]+$/ #ending alternates between / and space; / are suppressed for first two rows
}
a
}
puts g[7,3]
puts g[5,5]
Output
As I was finishing debugging, I noticed an ambiguity in the spec. Where w+1 is divisible by 4, the first and last x coordinates are odd, and there is no ambiguity. But where w-1 is divisible by 4 the first and last x coordinates are even. I assumed that the first and last columns should be offset below the next ones. But then I read the previous question and noted in that case it was the odd columns that should be offset below the even ones (note for w-1 divisible by 4 it is not possible to do both.)
That distinction was not made in this question, however. I will leave this up to OP's judgement and rework if necessary, though I'd prefer not to have to.
_____ _____ _____
/ \ / \ / \
_____/ -2,-1 \_____/ 0,-1 \_____/ 2,-1 \_____
/ \ / \ / \ / \
/ -3,-1 \_____/ -1,-1 \_____/ 1,-1 \_____/ 3,-1 \
\ / \ / \ / \ /
\_____/ -2,0 \_____/ 0,0 \_____/ 2,0 \_____/
/ \ / \ / \ / \
/ -3,0 \_____/ -1,0 \_____/ 1,0 \_____/ 3,0 \
\ / \ / \ / \ /
\_____/ -2,1 \_____/ 0,1 \_____/ 2,1 \_____/
/ \ / \ / \ / \
/ -3,1 \_____/ -1,1 \_____/ 1,1 \_____/ 3,1 \
\ / \ / \ / \ /
\_____/ \_____/ \_____/ \_____/
_____ _____
/ \ / \
_____/ -1,-2 \_____/ 1,-2 \_____
/ \ / \ / \
/ -2,-2 \_____/ 0,-2 \_____/ 2,-2 \
\ / \ / \ /
\_____/ -1,-1 \_____/ 1,-1 \_____/
/ \ / \ / \
/ -2,-1 \_____/ 0,-1 \_____/ 2,-1 \
\ / \ / \ /
\_____/ -1,0 \_____/ 1,0 \_____/
/ \ / \ / \
/ -2,0 \_____/ 0,0 \_____/ 2,0 \
\ / \ / \ /
\_____/ -1,1 \_____/ 1,1 \_____/
/ \ / \ / \
/ -2,1 \_____/ 0,1 \_____/ 2,1 \
\ / \ / \ /
\_____/ -1,2 \_____/ 1,2 \_____/
/ \ / \ / \
/ -2,2 \_____/ 0,2 \_____/ 2,2 \
\ / \ / \ /
\_____/ \_____/ \_____/