Me Want Honeycomb

39

2

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.

Calvin's Hobbies

Posted 2015-05-17T02:35:25.120

Reputation: 84 000

13Do you play a lot of Catan? – user3490 – 2015-05-17T11:15:17.853

@user3490 In fact I do ^^ – Calvin's Hobbies – 2015-05-17T11:17:02.413

2Next week on PCG: write a Catan board generator? – user3490 – 2015-05-17T11:17:56.923

7It should have an input IMO, in your case it should be 3. – user3819867 – 2015-05-17T12:06:13.770

3@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. – Calvin's Hobbies – 2015-05-17T18:26:15.903

Answers

33

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.

Dennis

Posted 2015-05-17T02:35:25.120

Reputation: 196 637

2This is brilliant. Nice work. – Alex A. – 2015-05-17T19:10:06.370

28

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.

xnor

Posted 2015-05-17T02:35:25.120

Reputation: 115 687

22

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.

Dennis

Posted 2015-05-17T02:35:25.120

Reputation: 196 637

10

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.

Reto Koradi

Posted 2015-05-17T02:35:25.120

Reputation: 4 870

2For the golfed one, you could use implicit-int and drop the int. – luser droog – 2015-05-17T09:28:52.123

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;} – Dennis – 2015-05-17T21:29:05.507

7

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]}

primo

Posted 2015-05-17T02:35:25.120

Reputation: 30 891

111.times saves 2 bytes – Mitch Schwartz – 2015-06-17T20:28:09.590

6

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>

edc65

Posted 2015-05-17T02:35:25.120

Reputation: 31 086

6

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      \\__/";

Timo

Posted 2015-05-17T02:35:25.120

Reputation: 181

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. – Ismael Miguel – 2015-05-18T09:09:22.137

1Thank you, I learn something new every time I try to golf hehe. – Timo – 2015-05-18T09:16:07.073

You are welcome. Here is a 99-byte long solution: https://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.

– Ismael Miguel – 2015-05-18T09:17:26.883

Meanwhile, I've reduced it 2 bytes. Now it has 97 bytes. – Ismael Miguel – 2015-05-18T09:24:09.813

Playing around, I've reduced that file to 88 bytes. On it, one thing to look out is that I've replaced each group of 4 spaced by a tab (\t). This means that you slim down 3 bytes. I will paste an hex dump of the file (or similar), just to be sure that everybody has it right and that the browser doesn't replace the tabs with 4 spaces. – Ismael Miguel – 2015-05-18T09:36:31.800

1Here 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. – Ismael Miguel – 2015-05-18T09:44:49.843

For me the \t is 4 spaces too long, I'm running it in the Windows Command Promt. – Timo – 2015-05-18T09:46:48.110

Tha't alright. As long as you can reproduce it. That means, if it works under a certain environment, and someone else can pick up and reproduce the same results, then it's all good. You can check the ideone link (https://ideone.com/WHWEZS) showing it working fine. It's the same code as before, but with the tabs and newlines replaced. As an alternative, you can click on the icon that looks like <> and paste this: <script src="http://ideone.com/e.js/WHWEZS" type="text/javascript" ></script>.

– Ismael Miguel – 2015-05-18T09:50:37.613

4

Lua 146

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

(newlines added for clarity)

Kyle Kanos

Posted 2015-05-17T02:35:25.120

Reputation: 4 270

1Isn't this code longer than the desired output because it just contains the output plus escaping and string handling stuff? – Caleb – 2015-05-17T17:32:16.223

6@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. – Kyle Kanos – 2015-05-17T17:45:52.573

2But 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. – Kyle Kanos – 2015-05-17T17:50:06.963

3

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.

lrn

Posted 2015-05-17T02:35:25.120

Reputation: 521

3

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
    `)

nderscore

Posted 2015-05-17T02:35:25.120

Reputation: 4 912

Nice one. .substr(+x+z,16-x-x) -> .slice(+x+z,16-x+z) -1 – edc65 – 2015-05-18T05:12:20.057

@edc65 nice catch! – nderscore – 2015-05-18T05:19:30.310

Quick question: Why is it +x instead of just x? – Fund Monica's Lawsuit – 2015-05-19T00:37:42.743

1@QPaysTaxes It's to cast x to a number. Without it, it would concatenate z – nderscore – 2015-05-19T00:50:06.733

2

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])

Matty

Posted 2015-05-17T02:35:25.120

Reputation: 471

2

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\__/
============
       __
    __/  \__
 __/  \__/  \__
/  \__/  \__/  \
\__/  \__/  \__/
/  \__/  \__/  \
\__/  \__/  \__/
/  \__/  \__/  \
\__/  \__/  \__/
   \__/  \__/
      \__/

randomra

Posted 2015-05-17T02:35:25.120

Reputation: 19 909

1

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)

SuperJedi224

Posted 2015-05-17T02:35:25.120

Reputation: 11 342