40
\$\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.
Martin Ender
198k67 gold badges455 silver badges998 bronze badges
asked May 17, 2015 at 2:35
\$\endgroup\$
5
  • 13
    \$\begingroup\$ Do you play a lot of Catan? \$\endgroup\$ Commented May 17, 2015 at 11:15
  • \$\begingroup\$ @user3490 In fact I do ^^ \$\endgroup\$ Commented May 17, 2015 at 11:17
  • 2
    \$\begingroup\$ Next week on PCG: write a Catan board generator? \$\endgroup\$ Commented May 17, 2015 at 11:17
  • 8
    \$\begingroup\$ It should have an input IMO, in your case it should be 3. \$\endgroup\$ Commented May 17, 2015 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\$ Commented May 17, 2015 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.

answered May 17, 2015 at 5:46
\$\endgroup\$
1
  • 2
    \$\begingroup\$ This is brilliant. Nice work. \$\endgroup\$ Commented May 17, 2015 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.

answered May 17, 2015 at 4:46
\$\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.
answered May 17, 2015 at 2:54
\$\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.

answered May 17, 2015 at 5:13
\$\endgroup\$
2
  • 2
    \$\begingroup\$ For the golfed one, you could use implicit-int and drop the int . \$\endgroup\$ Commented May 17, 2015 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\$ Commented May 17, 2015 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]}
answered May 17, 2015 at 5:55
\$\endgroup\$
1
  • 1
    \$\begingroup\$ 11.times saves 2 bytes \$\endgroup\$ Commented Jun 17, 2015 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>

answered May 17, 2015 at 10:35
\$\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 \\__/";
answered May 18, 2015 at 7:15
\$\endgroup\$
8
  • \$\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\$ Commented May 18, 2015 at 9:09
  • 1
    \$\begingroup\$ Thank you, I learn something new every time I try to golf hehe. \$\endgroup\$ Commented May 18, 2015 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\$ Commented May 18, 2015 at 9:17
  • \$\begingroup\$ Meanwhile, I've reduced it 2 bytes. Now it has 97 bytes. \$\endgroup\$ Commented May 18, 2015 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\$ Commented May 18, 2015 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)

answered May 17, 2015 at 2:52
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Isn't this code longer than the desired output because it just contains the output plus escaping and string handling stuff? \$\endgroup\$ Commented May 17, 2015 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\$ Commented May 17, 2015 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\$ Commented May 17, 2015 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.

answered May 17, 2015 at 14:01
\$\endgroup\$
3
\$\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])
answered May 17, 2015 at 19:34
\$\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
 `)
answered May 17, 2015 at 23:09
\$\endgroup\$
4
  • \$\begingroup\$ Nice one. .substr(+x+z,16-x-x) -> .slice(+x+z,16-x+z) -1 \$\endgroup\$ Commented May 18, 2015 at 5:12
  • \$\begingroup\$ @edc65 nice catch! \$\endgroup\$ Commented May 18, 2015 at 5:19
  • \$\begingroup\$ Quick question: Why is it +x instead of just x? \$\endgroup\$ Commented May 19, 2015 at 0:37
  • 1
    \$\begingroup\$ @QPaysTaxes It's to cast x to a number. Without it, it would concatenate z \$\endgroup\$ Commented May 19, 2015 at 0:50
3
\$\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\__/
============
 __
 __/ \__
 __/ \__/ \__
/ \__/ \__/ \
\__/ \__/ \__/
/ \__/ \__/ \
\__/ \__/ \__/
/ \__/ \__/ \
\__/ \__/ \__/
 \__/ \__/
 \__/
answered May 28, 2015 at 4:18
\$\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)
answered May 18, 2015 at 12:23
\$\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.