15
\$\begingroup\$

We once made a Hexagony template without actually knowing it. But after a bit of experience with Hexagony, it becomes apparent that it is not enough; sometimes the source code is too short for the given hexagon, and you get totally unexpected results.

So I came up with an idea: a template that gives a hint when the code is too short.

For the background: Hexagony detects the smallest hexagonal grid that fits the source code, and then fills each spot in the grid with each char in row-by-row fashion. E.g. the code

abcdefg@

contains 8 characters, and the smallest grid that can fit this is of size 3 (size 2 grid has only 7 spots)

  . . .
 . . . .
. . . . .
 . . . .
  . . .

so the code above is laid out like this:

  a b c
 d e f g
@ . . . .
 . . . .
  . . .

Now, to ensure that the code being written is actually laid out on the hexagon of size 3, the programmer has to make sure that the code has at least 8 characters; in other words, at least one of the spots marked * must be occupied by a command:

  . . .
 . . . .
* * * * *
 * * * *
  * * *

Math note: the number of spots in the hexagonal grid of size \$n \ge 1\$ is \$a(n)=3n(n-1)+1\$ (A003215). Since the Hexagony interpreter only has hexagon sizes of 1 and higher, \$a(0)\$ is undefined for this challenge.

Task

Given a positive integer n, draw a hexagonal grid like the one above so that

  • the first \$a(n-1)\$ spots are drawn with one kind of marker (e.g. .) and
  • the rest are drawn with another (e.g. *).

For \$n=1\$, it is allowed to output any of the two possible grids (single . or single *).

For output format:

  • You can choose the two markers, but the two must be distinct and not a whitespace character.
  • Extra leading and trailing whitespaces, and whitespaces at the end of each line are allowed, as long as it doesn't break the hexagonal layout.
  • Outputting as a list of strings (lines) is OK.

Standard rules apply. Shortest code in bytes wins.

Test cases

n=1
*
or
.

n=2
 . *
* * *
 * *

n=3
  . . .
 . . . .
* * * * *
 * * * *
  * * *

n=4
   . . . .
  . . . . .
 . . . . . .
. . . . * * *
 * * * * * *
  * * * * *
   * * * *

n=5
    . . . . .
   . . . . . .
  . . . . . . .
 . . . . . . . .
. . . . . . . . .
 . . * * * * * *
  * * * * * * *
   * * * * * *
    * * * * *
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Bonus points for anyone who does this in Hexagony? \$\endgroup\$ Aug 12, 2022 at 13:52

7 Answers 7

4
\$\begingroup\$

C (clang), 92 bytes

Outputs a leading newline.

x,y,z;f(n){for(x=n,z=3*n*--n;~z;)printf(!y--?y=n-~n-abs(--x),"\n%*.s":z--<6*n?"* ":". ",x);}

Try it online!

Some ideas are drawn from @Quentin's answer to the other hexagon challenge.

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 29 bytes

NθFθ«P^×*θ→→»‖B↓UM✂KA⁰±×⁶⊖θ¹.

Try it online! Link is to verbose version of code. Explanation: Based on my golf to @KevinCruijssen's Charcoal answer to the linked question, except at the very end I replace all but the last 6n-6 *s with .s.

\$\endgroup\$
2
\$\begingroup\$

lin, 76 bytes

1-.#n.n.>.n.<0\;.'.* <ls"\# \, ?s".n3*.n1- *1+ e*
1+.n +"# ".~ rep \.n5* pad

Try it here!

For testing purposes:

1 10 .-> ( ; outln n\ out ).'
1-.#n.n.>.n.<0\;.'.* <ls"\# \, ?s".n3*.n1- *1+ e*
1+.n +"# ".~ rep \.n5* pad

Explanation

Prettified code:

1-.#n .n.> .n.< 0 \;.'.* <ls .;
  1+ .n + "# ".~ rep \ .n5* pad
( \# \, ?s ) .n3* .n1- * 1+ e*
  • 1-.#n input - 1 as \$n\$
  • .n.> .n.< 0 create palindromic range \$[0, n) \cup [n, 0]\$
  • \;.' for each \$x\$...
    • 1+ .n + "# ".~ rep repeat # \$x+n+1\$ times
    • \ .n5* pad pad with spaces to \$5n\$
  • .* <ls join stack with newlines
  • (...) .n3* .n1- * 1+ e* execute \$3n(n-1)+1\$ times...
    • \# \, ?s replace first # with ,
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 21 20 bytes

<‚εxŸ¨„1 ×û.c}`Sþ0.;

-1 byte thanks to @Steffan.

Outputs 1 for * and 0 for ., with \$n=1\$ being * (1) (thus \$a(0)=0\$).

Try it online or verify the first 10 test cases.

Explanation:

<             # Decrease the (implicit) input-integer by 1
 ‚            # Pair it with the (implicit) input: [input,input-1]
  ε           # Map `y` over this pair:
   x          #  Double the current value (without popping it)
    Ÿ         #  Pop both, and push a list in the range [y,2y]
     ¨        #  Remove the last item to make the range [y,2y)
      „1 ×    #  Repeat string "1 " that many times†
          û   #  Palindromize the list
           .c #  Join the list by newlines, and pad leading spaces to centralize it
  }`          # After the map: Pop and push both the input'th and (input-1)'th hexagons
              # separated to the stack
    S         # Convert the (input-1)'th hexagon from a string to a list of characters
     þ        # Only keep the digits of these characters
       .;     # Replace each first digit occurrence in the input'th hexagon
      0       # to a 0†
              # (after which the result is output implicitly)

† Any other digits besides 1/0 could be used.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ DL+< can just be x٬ for -1 byte. (That makes you beat Vyxal :() \$\endgroup\$
    – naffetS
    Aug 12, 2022 at 22:07
  • \$\begingroup\$ @Steffan Thanks! :) \$\endgroup\$ Aug 13, 2022 at 10:06
0
\$\begingroup\$

x86-64 machine code, 51 bytes

56 B8 20 C7 07 85 99 59 A8 AE 01 D1 75 02 F7 DA 51 F3 AA 89 F1 66 F3 AB 88 0F 59 29 D6 39 F1 75 E2 88 E0 6B CE 06 E3 0A FD AE 75 FD FE 4F 01 E2 F8 FC C3

Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes in RDI an address at which to place the result, as a null-terminated byte string in ISO-8859-1, and takes the number \$n\$ in ESI.

In assembly:

f:  push rsi        #
    .byte 0xB8      # ┐mov eax, 0x8507C720 
    .byte 0x20      # │
l0: .byte 0xC7      # │               ┐mov DWORD PTR [rdi], 0xA8599985
    .byte 0x07      # │               │
    .byte 0x85      # ┘               │
    .byte 0x99      # ╴cdq            │
    .byte 0x59      # ╴pop rcx        │
    .byte 0xA8      # ┐test al, 0xAE  ┘
    .byte 0xAE      # ┘               ╴scasb
    add ecx, edx
    jnz s
    neg edx
s:  push rcx
    rep stosb
    mov ecx, esi
    rep stosw
    mov [rdi], cl
    pop rcx
    sub esi, edx
    cmp ecx, esi
    jne l0
    mov al, ah
    imul ecx, esi, 6
    jrcxz e
    std
l1: scasb
    jne l1
    dec BYTE PTR [rdi+1]
    loop l1
    cld
e:  ret
  • ECX and ESI both start out being equal to \$n\$.
  • At first, ECX is reduced by 1 at the start of each iteration, for the number of spaces at the start of the line.
  • At first, ESI is increased by 1 at the end of each iteration, for the number of spots in the line.
  • When ECX hits 0, at the middle line, those changes are reversed: from then on, ECX increases and ESI decreases. The neg edx instruction does this.
  • EDX is initialised to 1 using the 1-byte cdq instruction (sign-extend from EAX). This requires the high bit of EAX to be 1; because of the way the overlapping instructions worked out, this necessitated using 0x85 (NEL) as a newline instead of 0x0A (LF). (Because TIO's output mechanism does not handle NEL, the additional code in the TIO demonstration converts NEL to LF.)
  • The null terminator is added using mov [rdi], cl in the middle of the loop, taking advantage of ECX being 0 after rep stosw counts it down. This actually adds a null byte at the end of every line, but it is overwritten by the NEL except at the end.
  • The final part of the code runs backwards through the string and modifies the last \$6(n-1)\$ spots.
\$\endgroup\$
0
\$\begingroup\$

Vyxal, 21 bytes

‹"ƛdr‛a *∞øĊ⁋;÷Ǎ(n0øḞ

Try it Online!

Port of Kevin Cruijssen's 05AB1E answer.

\$\endgroup\$
0
\$\begingroup\$

Knight, 110 105 bytes

;=n+~1P;=c~1;=i+1*2nW+1=i-iT;O+*' '=xI>=x-n iFx~x'\';=j~2;W<=j+1j-*2n xI<c-**3n n*3n;=c+1cO'. \'O'* \'O''

100% can be golfed but I'm too lazy to do that lol.

Try It Online!

Test Suite up to n=10

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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