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.
-
13\$\begingroup\$ Do you play a lot of Catan? \$\endgroup\$user3490– user34902015年05月17日 11:15:17 +00:00Commented May 17, 2015 at 11:15
-
\$\begingroup\$ @user3490 In fact I do ^^ \$\endgroup\$Calvin's Hobbies– Calvin's Hobbies2015年05月17日 11:17:02 +00:00Commented May 17, 2015 at 11:17
-
2\$\begingroup\$ Next week on PCG: write a Catan board generator? \$\endgroup\$user3490– user34902015年05月17日 11:17:56 +00:00Commented May 17, 2015 at 11:17
-
8\$\begingroup\$ It should have an input IMO, in your case it should be 3. \$\endgroup\$user3819867– user38198672015年05月17日 12:06:13 +00:00Commented 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\$Calvin's Hobbies– Calvin's Hobbies2015年05月17日 18:26:15 +00:00Commented May 17, 2015 at 18:26
13 Answers 13
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.
-
2\$\begingroup\$ This is brilliant. Nice work. \$\endgroup\$Alex A.– Alex A.2015年05月17日 19:10:06 +00:00Commented May 17, 2015 at 19:10
Python 2, 73
i=0
exec"k=max(7-i,i-24,0);print' '*k+('\__/ '*9)[i:][k:16-k];i+=3;"*11
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.
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.
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.
-
2\$\begingroup\$ For the golfed one, you could use implicit-int and drop the
int. \$\endgroup\$luser droog– luser droog2015年05月17日 09:28:52 +00:00Commented 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\$Dennis– Dennis2015年05月17日 21:29:05 +00:00Commented May 17, 2015 at 21:29
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]}
-
1\$\begingroup\$
11.timessaves 2 bytes \$\endgroup\$Mitch Schwartz– Mitch Schwartz2015年06月17日 20:28:09 +00:00Commented Jun 17, 2015 at 20:28
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>
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 \\__/";
-
\$\begingroup\$ Welcome to Programming Puzzles and Code Golf. Your PHP code can be reduced a lot more. You can use
<?instead of<?phpto 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 theechoto further reduce it's length. Also, you don't need that space between theechoand the string. \$\endgroup\$Ismael Miguel– Ismael Miguel2015年05月18日 09:09:22 +00:00Commented May 18, 2015 at 9:09 -
1\$\begingroup\$ Thank you, I learn something new every time I try to golf hehe. \$\endgroup\$Timo– Timo2015年05月18日 09:16:07 +00:00Commented 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\$Ismael Miguel– Ismael Miguel2015年05月18日 09:17:26 +00:00Commented May 18, 2015 at 9:17 -
\$\begingroup\$ Meanwhile, I've reduced it 2 bytes. Now it has 97 bytes. \$\endgroup\$Ismael Miguel– Ismael Miguel2015年05月18日 09:24:09 +00:00Commented 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\twith a tab character and\nwith a real newline. \$\endgroup\$Ismael Miguel– Ismael Miguel2015年05月18日 09:44:49 +00:00Commented May 18, 2015 at 9:44
Lua 146
T=" __\n __/ \\__\n __/ \\__/ \\__\n"
S="/ \\__/ \\__/ \\\n\\__/ \\__/ \\__/\n"
B=" \\__/ \\__/\n \\__/"
io.write(T,S,S,S,B)
(newlines added for clarity)
-
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– Caleb2015年05月17日 17:32:16 +00:00Commented 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
Sthree times. \$\endgroup\$Kyle Kanos– Kyle Kanos2015年05月17日 17:45:52 +00:00Commented 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\$Kyle Kanos– Kyle Kanos2015年05月17日 17:50:06 +00:00Commented May 17, 2015 at 17:50
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.
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])
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
`)
-
\$\begingroup\$ Nice one.
.substr(+x+z,16-x-x)->.slice(+x+z,16-x+z)-1 \$\endgroup\$edc65– edc652015年05月18日 05:12:20 +00:00Commented May 18, 2015 at 5:12 -
\$\begingroup\$ @edc65 nice catch! \$\endgroup\$nderscore– nderscore2015年05月18日 05:19:30 +00:00Commented May 18, 2015 at 5:19
-
\$\begingroup\$ Quick question: Why is it
+xinstead of justx? \$\endgroup\$anon– anon2015年05月19日 00:37:42 +00:00Commented May 19, 2015 at 0:37 -
1\$\begingroup\$ @QPaysTaxes It's to cast
xto a number. Without it, it would concatenatez\$\endgroup\$nderscore– nderscore2015年05月19日 00:50:06 +00:00Commented May 19, 2015 at 0:50
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\__/
============
__
__/ \__
__/ \__/ \__
/ \__/ \__/ \
\__/ \__/ \__/
/ \__/ \__/ \
\__/ \__/ \__/
/ \__/ \__/ \
\__/ \__/ \__/
\__/ \__/
\__/
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)
Explore related questions
See similar questions with these tags.