15
\$\begingroup\$

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 , 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\___
\ / \ / 
asked Jan 25, 2016 at 21:45
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Related \$\endgroup\$ Commented Jan 25, 2016 at 22:04

1 Answer 1

2
\$\begingroup\$

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 \
\ / \ / \ /
 \_____/ \_____/ \_____/
answered Jan 27, 2016 at 9:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.