39
\$\begingroup\$

Write the shortest program that prints this ASCII art section of a hexagonal tiling or honeycomb:

       __
    __/  \__
 __/  \__/  \__
/  \__/  \__/  \
\__/  \__/  \__/
/  \__/  \__/  \
\__/  \__/  \__/
/  \__/  \__/  \
\__/  \__/  \__/
   \__/  \__/
      \__/
  • No input should be taken.
  • Output to stdout or your language's closest alternative.
  • Instead of a program, you may write a named function that takes no parameters and prints the result normally or returns it as a string.
  • The output may have any number of leading and/or trailing newlines and each line in the output may have any number of leading and/or trailing spaces (as long as the pattern lines up properly.)
  • The shortest code in bytes wins.
\$\endgroup\$
  • 13
    \$\begingroup\$ Do you play a lot of Catan? \$\endgroup\$ – user3490 May 17 '15 at 11:15
  • \$\begingroup\$ @user3490 In fact I do ^^ \$\endgroup\$ – Calvin's Hobbies May 17 '15 at 11:17
  • 2
    \$\begingroup\$ Next week on PCG: write a Catan board generator? \$\endgroup\$ – user3490 May 17 '15 at 11:17
  • 7
    \$\begingroup\$ It should have an input IMO, in your case it should be 3. \$\endgroup\$ – user3819867 May 17 '15 at 12:06
  • 3
    \$\begingroup\$ @user3819867 I did consider that but preferred this. It's too late to change but not too late for anyone to make a related challenge. \$\endgroup\$ – Calvin's Hobbies May 17 '15 at 18:26

13 Answers 13

33
\$\begingroup\$

CJam, 45 43 42 41 40 bytes

741e8 36+Ab"\__/  "38*21/.{G2$-<\S*.e<N}

Try it online in the CJam interpreter.

How it works

"\__/  "38*21/

repeats the pattern \__/ 38 times and splits it into chunks of length 21. If the chunks were separated by linefeeds, this would be the result:

\__/  \__/  \__/  \__
/  \__/  \__/  \__/  
\__/  \__/  \__/  \__
/  \__/  \__/  \__/  
\__/  \__/  \__/  \__
/  \__/  \__/  \__/  
\__/  \__/  \__/  \__
/  \__/  \__/  \__/  
\__/  \__/  \__/  \__
/  \__/  \__/  \__/  
\__/  \__/  \__/  

This clearly contains the desired honeycomb. All that's left to do is to replace some characters with spaces, cut off some others and actually introduce the linefeeds.

741e8 36+Ab

generates the integer 74 100 000 036 and converts it into the array [7 4 1 0 0 0 0 0 0 3 6]. Each array element encodes the number of leading characters of the corresponding line that have to get replaced with spaces. By subtracting this number from 16, we also obtain the correct length for this line.

.{            } e# Execute for each pair of a digit D and a line L:
  G2$-<         e#   Chop off L after 16 - D characters.
       \S*      e#   Push a string of D spaces.
          .e<   e#   Compute the vectorized minimum.
             N  e#   Push a linefeed.

Since a space has a lower code point than the other characters of L and vectorized operators leave the characters of the longer string that do not correspond to one of the shorter one untouched, .e< replaces the first D characters with spaces.

\$\endgroup\$
  • 2
    \$\begingroup\$ This is brilliant. Nice work. \$\endgroup\$ – Alex A. May 17 '15 at 19:10
28
\$\begingroup\$

Python 2, 73

i=0
exec"k=max(7-i,i-24,0);print' '*k+('\__/  '*9)[i:][k:16-k];i+=3;"*11

See it run.

For each of the 11 output rows, computes the number of leading spaces k as a maximum of three linear functions that form the envelope of the left side of the hexagon. Because the diagonal lines have slope 3 and -3, it's better to index the row number as i=0,3,...30.

To create the hexagon mesh, we first tile enough of the unit '\__/ '. Then, shifting [i:] realigns it by 3 for odd rows. Finally, we take the needed portion [k:16-k] of it, leaving a margin of k on the left and right.

\$\endgroup\$
22
\$\begingroup\$

CJam, 65 56 55 bytes

"Ý6TNð*¯5"303b4b["/\_")"_ "4*S]f=sB/z{_W%"\/"_W%erN}/

Try it online in the CJam interpreter.

Idea

The right half of each line is a reversed copy of the left half with slashes and backslashes swapped. Therefore, it suffices to encode the left half of the honeycomb:

       _
    __/ 
 __/  \_
/  \__/ 
\__/  \_
/  \__/ 
\__/  \_
/  \__/ 
\__/  \_
   \__/ 
      \_

Rather than analyzing this pattern line by line, we can analyze it column by column:

   /\/\/\  
  _ _ _ _  
  _ _ _ _  
  /\/\/\/\ 
 _ _ _ _ _ 
 _ _ _ _ _ 
 /\/\/\/\/\
_ _ _ _ _ _

Obvious patterns emerge:

  • The string _ _ _ _ occurs five times.
  • Every / is followed by a \.

By replacing every /\, _, _ _ _ _ and space with a number from 0 to 3, we can convert the resulting array from a base 4 number to a higher base and store the complete pattern in a compact fashion.

Code

"Ý6TNð*¯5"303b4b  e# Convert the string from base 303 to base 4.
["/\_")"_ "4*S]f= e# Replace each resulting digit by the corresponding item of the array
                  e# ["/\" "_" "_ _ _ _ " " "].
sB/               e# Split into strings of length 11.
z                 e# Zip: transpose rows with columns.
{             }/  e# For each string:
 _W%              e#     Push a reversed copy.
    "\/"_W%er     e#     Swap slashes and backslashes.
             N    e#     Push a linefeed.
\$\endgroup\$
10
\$\begingroup\$

C, 148 144 140 bytes

k,r,c,d,p;f(){for(;k<187;k++){r=k/17;c=k%17;d=c+r%2*3;p=3*r+c-7<33u&3*r-c+8<33u;putchar(c==16?10:p&(d+5)%6<2?95:p&d%6==3?47:!p|d%6?32:92);}}

With whitespace, without compiler warnings, and before some code tweaks to save a few bytes:

#include <stdio.h>

int k, r, c, d, p;

void f() {
    for ( ; k < 187; k++) {
        r = k / 17;
        c = k % 17;
        d = c + 3 * (r % 2);
        p = 3 * r + c - 7 < 33u && 3 * r - c + 8 < 33u;
        putchar(
            c == 16 ? 10 :
            p && (d + 5) % 6 < 2 ? 95 :
            p && d % 6 == 3 ? 47 :
            p && d % 6 == 0 ? 92 :
            32);
    }
}

This approach does not use any character/string tables. It loops over all 187 (11 rows, 17 columns including newlines), and decides which character to print for each position, based on a combination of conditions.

The conditions include a test for being inside/outside the 4 corners, using 4 line equations, with the result stored in variable p. The rest is then mostly repeating every 6 characters, with the odd rows shifted by 3 characters relative to the even rows.

\$\endgroup\$
  • 2
    \$\begingroup\$ For the golfed one, you could use implicit-int and drop the int . \$\endgroup\$ – luser droog May 17 '15 at 9:28
  • \$\begingroup\$ A few micro-improvements: k;f(r,c,d,p){for(;k<187;putchar(c>15?10:p&d<2&p?95:p&d<3?47:!p|d-5?32:92))r=k/17,c=k++%17,d=(5+c+r%2*3)%6,p=3*r+c-7<33u&3*r-c+8<33u;} \$\endgroup\$ – Dennis May 17 '15 at 21:29
7
\$\begingroup\$

Ruby - 78 Bytes

(-5..5).map{|i|puts' '*(j=[i.abs*3-i/6-9,0].max)+('/  \__'*4)[j+i%2*3,16-j*2]}

A transcription of xnor's solution (69 Bytes):

11.times{|i|puts' '*(j=[7-i*=3,i-24,0].max)+('\__/  '*9)[i+j,16-j*2]}
\$\endgroup\$
  • 1
    \$\begingroup\$ 11.times saves 2 bytes \$\endgroup\$ – Mitch Schwartz Jun 17 '15 at 20:28
6
\$\begingroup\$

JavaScript (ES6), 129 130

That's a pure string replace/replace/replace ... not taking advantage of any geometric property.

Using template strings, all newlines are significant and count.

Run snippet in Firefox to test

f=_=>`70
405
 055
9992 3051
6301`[R='replace'](/9/g,`55123
30551
`)[R](/5/g,1230)[R](/\d/g,n=>['__','/',,'\\'][n]||' '.repeat(n))

// TEST

O.innerHTML = f()
<pre id=O></pre>

\$\endgroup\$
6
\$\begingroup\$

PHP - 139 137 107 101 91 87 bytes

I don't know if this is the best way to golf it but here is my try at it:

30 36 46 -50 bytes thanks to Ismael Miguel

Test it online here

<?='       __
    __',$a='/  \__',"
 __$a$a
",$c="$a$a/  \
\__$a$a/
","$c$c   \__$a/
      \__/";

<script src="http://ideone.com/e.js/WHWEZS" type="text/javascript" ></script>

old code:

<?php $a="/  \\__";$c=$a.$a."/  \\\n\__".$a.$a."/\n";echo "       __\n    __".$a."\n __".$a,$a."\n".$c,$c,$c."   \\__".$a."/\n      \\__/";
\$\endgroup\$
  • \$\begingroup\$ Welcome to Programming Puzzles and Code Golf. Your PHP code can be reduced a lot more. You can use <? instead of <?php to save 3 bytes. Instead of $c=$a.$a."/ \\\n\__".$a.$a."/\n";, you can write $c="$a$a/ \\\n\__.$a$a/\n"; (since PHP expands variables in strings). You can apply the same logic to the echo to further reduce it's length. Also, you don't need that space between the echo and the string. \$\endgroup\$ – Ismael Miguel May 18 '15 at 9:09
  • 1
    \$\begingroup\$ Thank you, I learn something new every time I try to golf hehe. \$\endgroup\$ – Timo May 18 '15 at 9:16
  • \$\begingroup\$ You are welcome. Here is a 99-byte long solution: ideone.com/WHWEZS. It looks a mess, but it is a lot shorter. Instead of using \n, you can put a real newline and save 1 byte per line. \$\endgroup\$ – Ismael Miguel May 18 '15 at 9:17
  • \$\begingroup\$ Meanwhile, I've reduced it 2 bytes. Now it has 97 bytes. \$\endgroup\$ – Ismael Miguel May 18 '15 at 9:24
  • 1
    \$\begingroup\$ Here is a one-liner: <?="\t __\n\t__",$a='/ \__',"\n __$a$a\n",$c="$a$a/ \\\n\__$a$a/\n","$c$c \__$a/\n\t \__/";. Remember to replace the \t with a tab character and \n with a real newline. \$\endgroup\$ – Ismael Miguel May 18 '15 at 9:44
4
\$\begingroup\$

Lua 146

T="       __\n    __/  \\__\n __/  \\__/  \\__\n"
S="/  \\__/  \\__/  \\\n\\__/  \\__/  \\__/\n"
B="   \\__/  \\__/\n      \\__/"
io.write(T,S,S,S,B)

(newlines added for clarity)

\$\endgroup\$
  • 1
    \$\begingroup\$ Isn't this code longer than the desired output because it just contains the output plus escaping and string handling stuff? \$\endgroup\$ – Caleb May 17 '15 at 17:32
  • 6
    \$\begingroup\$ @Caleb: I suspect you've not actually counted & just guessed in making that comment. According to my text editor, there are 165 characters in the lattice (newlines included). I have 19 less characters due to repeating S three times. \$\endgroup\$ – Kyle Kanos May 17 '15 at 17:45
  • 2
    \$\begingroup\$ But you are correct that the escapes and newlines do limit my code's ability to compete in this particular game. But winning also isn't why I do this, it's for the fun & learning. \$\endgroup\$ – Kyle Kanos May 17 '15 at 17:50
3
\$\begingroup\$

Dart - 113

main({r:"/  \\__"}){print("       __\n    __$r\n __$r$r\n${"$r$r/  \\\n\\__$r$r/\n"*3}   \\__$r/\n      \\__/");}

Pure string-interpolation solution, nothing fancy. String operations like "substring" are too verbose to compete in practice.

Run it on DartPad.

\$\endgroup\$
3
\$\begingroup\$

Javascript (ES7 Draft), 96 94 93 bytes

Inspiration taken from a few solutions here...

Edit: -1 from edc65

f=z=>[for(x of[741e6]+36)' '.repeat(x)+'/  \\__'.repeat(4,z^=3).slice(+x+z,16-x+z)].join(`
`)

// For snippet demo:
document.write('<pre>'+f()+'</pre>');

Commented:

f=z=>[                                 
        for(x of [741e6] + 36)        // for each character "x" in "74100000036"
            ' '.repeat(x) +           // x spaces
            '/  \\__'.repeat(4,       // build pattern string
            z ^= 3).                  // toggle z offset (3) for even lines
            slice(+x + z, 16 - x + z) // get appropriate substring
    ].join(`                          // join with newlines
    `)
\$\endgroup\$
  • \$\begingroup\$ Nice one. .substr(+x+z,16-x-x) -> .slice(+x+z,16-x+z) -1 \$\endgroup\$ – edc65 May 18 '15 at 5:12
  • \$\begingroup\$ @edc65 nice catch! \$\endgroup\$ – nderscore May 18 '15 at 5:19
  • \$\begingroup\$ Quick question: Why is it +x instead of just x? \$\endgroup\$ – Fund Monica's Lawsuit May 19 '15 at 0:37
  • 1
    \$\begingroup\$ @QPaysTaxes It's to cast x to a number. Without it, it would concatenate z \$\endgroup\$ – nderscore May 19 '15 at 0:50
2
\$\begingroup\$

Python 3, 100 87 bytes

n=0x85208e08e08dd445
while n:l=n>>2&15;print(' '*(8-l)+('\__/  '*4)[n&3:n&3|l*2]);n>>=6

And a readable version of the code below. The idea is to hardcode the intervals (begin, length) and then pad with the correct amount of spaces to center the interval.

hexagon_string = '\__/  ' * 4
for i in range(11):
    # Pick the begin and length of the i-th interval using hardcoded numbers
    b = (0x00030303111 >> 4*i) & 3   # n is a combination of these two numbers
    l = (0x25888888741 >> 4*i) & 15  #
    # Print the interval with appropriate whitespace in front of it
    spaces = ' ' * (8-l)
    print(spaces + hexagon_string[b : b+l*2])
\$\endgroup\$
2
\$\begingroup\$

Retina, 66 bytes

<empty line>
sss __<LF>ssa__<LF> aa__<LF>lll dau<LF>ssdu
l
/daa<LF>\aau<LF>
a
ud
u
__/
d
s\
s

Each line should go to its own file and <LF> means actual newline in the file. 1 byte per extra file added to byte-count.

You can run the code as one file with the -s flag, keeping the <LF> markers and maybe changing them to newlines in the output for readability if you wish.

The algorithm is 5 simple substitute steps (change odd line content to even line content) starting from an empty input string. The results after each steps are (delimited by ='s):

sss __
ssa__
 aa__
lll dau
ssdu
============
sss __
ssa__
 aa__
/daa
\aau
/daa
\aau
/daa
\aau
 dau
ssdu
============
sss __
ssud__
 udud__
/dudud
\ududu
/dudud
\ududu
/dudud
\ududu
 dudu
ssdu
============
sss __
ss__/d__
 __/d__/d__
/d__/d__/d
\__/d__/d__/
/d__/d__/d
\__/d__/d__/
/d__/d__/d
\__/d__/d__/
 d__/d__/
ssd__/
============
sss __
ss__/s\__
 __/s\__/s\__
/s\__/s\__/s\
\__/s\__/s\__/
/s\__/s\__/s\
\__/s\__/s\__/
/s\__/s\__/s\
\__/s\__/s\__/
 s\__/s\__/
sss\__/
============
       __
    __/  \__
 __/  \__/  \__
/  \__/  \__/  \
\__/  \__/  \__/
/  \__/  \__/  \
\__/  \__/  \__/
/  \__/  \__/  \
\__/  \__/  \__/
   \__/  \__/
      \__/
\$\endgroup\$
1
\$\begingroup\$

Javascript, 154 151 bytes

b="\n",c="\t",d="/  \\",f="__",g="\\",h="/",a=f+d,j=a+a,i=d+j+b+g+j+f+h+b,k="   ";console.log(c+k+f+b+c+a+f+b+" "+j+f+b+i+i+i+k+g+a+f+h+b+c+"  "+g+f+h)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.