Your task: given an integer n
, generate an embedded hexagon pattern following the below rules, to the nth depth.
An embedded hexagon has the basic shape of this: (n=0
)
__
/ \
\__/
Embedded Hexagons n=1
and n=2
:
____
/ \ \
/\__/ \
\ /
\____/
________
/ \ \ \
/\__/ \ \
/\ / \
/ \____/ \
\ /
\ /
\ /
\________/
The length of each side is 2 times the length of the same side in the previous depth times two. The top and bottom sides are 2 characters long when n=0
and the rest start out as 1 character long. The non top-bottom side lengths should be 2^n
long (OEIS: A000079) and the top and bottom sides should follow the rule 2^(n+1)
(same OEIS).
The current hexagons are 0-indexed, you may chose to use 1-indexed if you want.
This is code-golf, so the shortest answer wins!
4 Answers 4
Charcoal, (削除) 40 (削除ここまで) 29 bytes
11 bytes saved thanks to @Neil by changing the while loop to a for-loop amongst other tricks
×ばつ__×ばつ__β↖β→↗β
Explanation (outdated)
This program starts with generating the largest hexagon, and then does the smaller ones one-by-one in a while loop (1-indexed). For reference, α
is the input number, β
is the variable that contains 2^(α-1)
and ι
is the iterating variable in the loop.
Nα # Take input and store in α
Wα« # While α do:
×ばつ_X2ι # Write "_"*(2**ι); this forms the top edge of the hexagon
↓ # Go down
AX2−ι1β # Assign 2**(ι-1) to β
↘β← # Write \ β times in a SE direction (top right edge) and then go left
↙β↑ # Write / β times in a SW direction (bottom right edge) and then go up
×ばつ_X2ι # Write the bottom edge
↖β→↗β # Just like before, write the top and bottom left edges
A−α1α # Decrement α
# Now the pointer is at the top left corner of the hexagon,
# from where the other smaller hexagons will soon be generated
-
\$\begingroup\$ I noticed there's no "Hello, World!" program for Charcoal yet. You should add it. \$\endgroup\$mbomb007– mbomb0072017年04月07日 21:09:25 +00:00Commented Apr 7, 2017 at 21:09
-
\$\begingroup\$ @mbomb007 Wouldn't that just be a duplicate of the trivial "this language prints its source file if it contains no commands" answer? \$\endgroup\$Neil– Neil2017年05月25日 20:58:40 +00:00Commented May 25, 2017 at 20:58
-
\$\begingroup\$ I saved some bytes when I realised that
×_X²ι
is the same as×__β
, and some more bytes by converting yourW
into aF
, which also avoids having to store the input number. Try it online!. \$\endgroup\$Neil– Neil2017年05月25日 21:12:42 +00:00Commented May 25, 2017 at 21:12 -
\$\begingroup\$ @Neil Thanks, that is pretty neat :) \$\endgroup\$user41805– user418052017年05月26日 06:20:12 +00:00Commented May 26, 2017 at 6:20
Haskell, (削除) 230 (削除ここまで) (削除) 217 (削除ここまで) 207 bytes
EDIT:
- -13 bytes: @xnor saw that my
#
could be justmax
. - -10 bytes: And also that
zipWith
andp
could be merged into a?
operator, and that I'd (somehow!) reimplementedreplicate
.
m
takes an Integer
and returns a String
.
m n=unlines.foldr1 o$((2^n)&).(2^)<$>[0..n]
l&t|a<-c[l,2*t]" _",b<-[c[l-i,1,2*t+2*i-2,1,l-i]" / \\ "|i<-[1..t]]=a:b++r(r<$>o[a]b)
c=(concat.).z replicate
o=max?' '?""
f?e=z f.(++repeat e)
r=reverse
z=zipWith
How it works
m
is the main function. It uses&
to generate the hexagons with proper padding, then folds them together witho
.l&t
generates a small hexagon of side lengtht
, padded inside a large one of side lengthl
, as a list ofString
lines.a
is the top line of the hexagon, with the underscores.b
is a list of the other lines in the upper half of the hexagon. The lines ofb
are centered in the padding, which is rectangular; this allows the next step to work.- The bottom half of the hexagon is
a
overlaid on top ofb
witho
, then reversed (both order of lines and within each line).
c
takes two arguments, a list of lengths and a string, and generates a string that has as many copies of each character in the original as the corresponding length, e.g.c[1,3,2]"abc" == "abbbcc"
. It is used in&
to generate the lines.o
takes two arguments representing pictures as lists of lines, and overlays the first, smaller one on top of the second one.- It is used both to combine hexagons and to add the bottom to each hexagon.
- It essentially works by using
?
twice to pad the first picture with infinitely many spaces both downwards and rightwards, then zipping together corresponding characters withmax
, which selects the non-space character if there is one.
(f?e)l m
pads a listl
by appending infinitely many 'e' elements, then zips the resulting list and the listm
with thef
function.
-
1\$\begingroup\$ Nice solution! I think
(#)
can bemax
. \$\endgroup\$xnor– xnor2017年04月08日 03:11:29 +00:00Commented Apr 8, 2017 at 3:11 -
1\$\begingroup\$ The zipping can be combined with
p
to save bytes:o=max?' '?"";f?e=z f.(++repeat e)
. Might be shorter pointfree. \$\endgroup\$xnor– xnor2017年04月08日 03:38:28 +00:00Commented Apr 8, 2017 at 3:38 -
2\$\begingroup\$
(\n->(<$[1..n]))
isreplicate
. \$\endgroup\$xnor– xnor2017年04月08日 03:47:16 +00:00Commented Apr 8, 2017 at 3:47 -
\$\begingroup\$ @xnor
replicate
? Now that's just embarassing. I'm just too used to<$[1..n]
or[1..n]>>
nearly always winning. However, I don't see how to shorten?
further. I already tried makingp
pointfree and the++
is just in the wrong spot, blowing up things withflip
. \$\endgroup\$Ørjan Johansen– Ørjan Johansen2017年04月08日 04:17:16 +00:00Commented Apr 8, 2017 at 4:17
JavaScript (ES6), 258 bytes
f=(n,s=` `.repeat(1<<n),p=(n?f(n-1):`
`).replace(/(.*)\n/g,s+`1ドル `+s)+s,t=`_`.repeat(2<<n))=>(s+t+s+`
`+s.replace(/ /g,"$'/$'$' $`$`$`$`\\$'\n")).replace(/ /g,(c,i)=>p[i+(1<<n>>1)])+s.replace(/ /g,"$`\\$`$` $'$'$'$'/$`\n").replace(/ +\/( *)\n$/,t+`/1ドル
`)
<input type=number min=0 oninput=o.textContent=f(+this.value)><pre id=o>
Explanation: For hexagons after the first, the previous hexagon is first generated and padded on each side (this relies on the output being a rectangle). (For the first heading, some dummy padding is created.) The top and top sides of the hexagon are generated, and all the spaces merged with the previous hexagon. (There's some trickery in order to get the hexagons to line up; this would be easier if extra margins were allowed.) The bottom sides of the hexagon are generated analogously to the top sides, and the bottom of the hexagon is then filled in. Care has to be taken to return rectangular output, including a trailing newline, for the recursion to work.
-
\$\begingroup\$ So, you're demonstrating that this, the Teflon one, and the Deep Dish Pizza one, are all really similar construction? That's kinda neat. \$\endgroup\$AdmBorkBork– AdmBorkBork2017年04月07日 20:37:23 +00:00Commented Apr 7, 2017 at 20:37
-
1\$\begingroup\$ @AdmBorkBork I have a few other answers that do that; those diagonal
/
s are popular in ASCII art and thereplace
method is a relatively cheap way of generating them in JavaScript. \$\endgroup\$Neil– Neil2017年04月07日 20:45:18 +00:00Commented Apr 7, 2017 at 20:45 -
\$\begingroup\$
1<<n>>1
: Nice symmetry ;-) \$\endgroup\$Luke– Luke2017年04月08日 20:51:30 +00:00Commented Apr 8, 2017 at 20:51 -
\$\begingroup\$ @Luke I could change the variable to, say,
v
but sadly the1
isn't symmetric in any of my usual fonts. \$\endgroup\$Neil– Neil2017年04月08日 20:55:42 +00:00Commented Apr 8, 2017 at 20:55
PHP, 337 Bytes
0 Indexing
$h=array_fill(0,1+2*$v=2**($c=$argn),str_pad("",4*$v));for(;1+$c;$c--)for($i=0;$i<$e=2**$c*2+1;$i++){$z=$e-$i<2;$y=$i&&$i<$e/2;$x=$i>=$e/2&$i<$e-1;$h[$i]=substr_replace($h[$i],$s=str_pad(!$y?$z|$x?"\\":"":"/",$e-1+$z-$y+$y*$i*2-$x+$x*2*($e-$i),$z|!$i?"_":" ").(!$y?$z|$x?"/":"":"\\"),$v-$z-$y*$i-$x*($e-$i),strlen($s));}echo join("\n",$h);
Expanded
$h=array_fill(0,1+2*$v=2**($c=$argn),str_pad("",4*$v)); # fill array with maximal width
for(;1+$c;$c--) # greatest hexagon to lowest
for($i=0;$i<$e=2**$c*2+1;$i++){ # loop through the rows
$z=$e-$i<2;$y=$i&&$i<$e/2;$x=$i>=$e/2&$i<$e-1; # booleans last first ad second half
$h[$i]=substr_replace($h[$i], # replace substring
$s=str_pad(
$z?"\\":($y?"/":($x?"\\":"")),
$e-1+$z-$y+$y*$i*2-$x+$x*2*($e-$i),
$z|!$i?"_":" "
).(!$z?!$y?$x?"/":"":"\\":"/"), # with string for smaller hexagon
$v-$z-$y*$i-$x*($e-$i), # at offset
strlen($s));
}
echo join("\n",$h); # Output
n
? \$\endgroup\$