13
\$\begingroup\$

Consider this spiral

###########
#
# #######
# #     #
# # ### #
# # # # #
# # # # #
# #   # #
# ##### #
#       #
#########

Starting in the centre:

  • The first line (upwards) has 3 characters.
  • The second line has the same number of characters (3)
  • Next, we add two chars (5) for the next two sides.
  • This pattern continues, two sides the same length then increase the length by 2.

I want to generate this spiral for N lines.

  • Write in any language.
  • The input/argument, etc. is the number of lines in your spiral.
  • Each line starts with the ending character of the previous line in the direction 90 degrees clockwise of the previous line.
  • I don't care how much whitespace is before or after each line, as long as the elements of the spiral line up.
  • Output text to draw the spiral with any non-whitespace character you choose.
  • Attempt to do this in the smallest number of bytes.

Test cases (using a hash as output):

N = 1

#
#
#

N = 2

###
#
#

N = 3

###
# #
# #
  #
  #

N = 10

###########
#
# #######
# #     #
# # ### #
# # # # #
# # # # #
# #   # #
# ##### #
#       #
#########
\$\endgroup\$
  • \$\begingroup\$ @Shaggy "Output text to draw the spiral with any non-whitespace character you choose." Yep, whatever you like. \$\endgroup\$ – AJFaraday Jun 26 '18 at 11:09
  • 3
    \$\begingroup\$ Related 1; Related 2. \$\endgroup\$ – Kevin Cruijssen Jun 26 '18 at 11:10
  • 3
    \$\begingroup\$ The initial image has an * instead of #. Expected? \$\endgroup\$ – Wernisch Jun 26 '18 at 11:56
  • \$\begingroup\$ @Wernisch It was intended to be a helpful starting point, but I suppose it's misleading. You can use any character you like. \$\endgroup\$ – AJFaraday Jun 26 '18 at 12:36
11
\$\begingroup\$

05AB1E, 13 11 bytes

Code:

Thanks to Emigna for saving two bytes!

LDÈ-Ì'#3Ý·Λ

Uses the 05AB1E encoding. Try it online!

Explanation

The lengths of each individual edge on the spiral starts with length 3 and gradually increases every two steps by two:

$$ 3, 3, 5, 5, 7, 7, 9,\dots $$

For a spiral with \$n\$ edges, we just need to trim this list to size \$n\$. This is done with the following piece of code:

L                # Create a list from [1 .. input]
 DÈ              # Duplicate and check for each number if even
   -             # Subtract that from the first list
    Ì            # Add 2

This basically gives us the desired list of lengths.

     '#          # Push the '#' character
       0246S     # Push the array [0, 2, 4, 6]
            Λ    # Write to canvas

The canvas works as a function that pops three parameters (where the rightmost parameter is popped first): <length(s)>, <char(s)>, <direction(s)>. The directions parameter is in this case a list of numbers. The numbers that correspond to the directions are:

$$ \left[\begin{array}{r} 7 & 0 & 1 \\ 6 & \circ & 2 \\ 5 & 4 & 3 \end{array}\right] $$

In this case, [0, 2, 4, 6] corresponds to the directions list [↑, →, ↓, ←]. The canvas iterates over each length retrieved from the list of lengths, uses the '#' character and cyclically iterates over the directions list.

\$\endgroup\$
  • \$\begingroup\$ 0246S = 3Ý· \$\endgroup\$ – Emigna Jun 27 '18 at 10:45
  • \$\begingroup\$ @Emigna Ah I did not think of that, thanks! \$\endgroup\$ – Adnan Jun 27 '18 at 14:06
6
\$\begingroup\$

Python 2, 176 170 165 161 157 bytes

g=lambda a,r:r and g(map(''.join,zip(*a))[::-1],r-1)or a
R=['#']
n=1
exec"R=g(['  '+l for l in g(R,n)][:-1]+[(n+2)*'#'],3*n);n+=1;"*input()
print'\n'.join(R)

Try it online!

Repeatedly: Uses g to rotate the nth iteration of the spiral into a 'canonical' position (similar to N=3 or N=7), adds a new segment by adding 2 spaces at the left of each existing row, then replacing the last row with all '#'s (resulting in a position comparable to N=4 or N=8), and finally using g again to rotate it back to the correct position. Lather, rinse, repeat.

\$\endgroup\$
4
\$\begingroup\$

Charcoal, 16 15 14 bytes

↶FN«¶×#⁺³⊗÷ι²↷

-2 bytes thanks to @Neil.

Try it online (verbose) or Try it online (pure).

Explanation:

Printing direction is to the right by default, and we want to start upwards, so we start by rotating 45 degrees counterclockwise:

PivotLeft();
↶

Then loop i in the range [0, input):

For(InputNumber()){ ... }
FN« ...

Print a new-line to mimic the effect of moving back one position:

Print("\n");
¶

Print "#" x amount of times in the current direction:

Print(Times("#", ... ));
×# ...

Where x is: 3 + i // 2 * 2:

Add(3,Doubled(IntegerDivide(i,2))
⁺³⊗÷ι²

And then rotate 45 degrees clockwise for the next iteration of the loop:

PivotRight();
↷
\$\endgroup\$
  • \$\begingroup\$ I assume there's no command in Charcoal for moving backwards? \$\endgroup\$ – Emigna Jun 26 '18 at 12:18
  • \$\begingroup\$ @Emigna Not sure, but I couldn't find it either. Was indeed looking for one myself when I was writing this answer. There is a Move with a given direction, as well as a Jump with given coordinates, but not a MoveBack unfortunately. \$\endgroup\$ – Kevin Cruijssen Jun 26 '18 at 12:22
  • 1
    \$\begingroup\$ ⊗÷ι² is a byte shorter than ⁻ι﹪ι². Also, you can get the effect of moving back by printing a \n before the #s, which will allow you to remove the »# for an additional overall byte saving. \$\endgroup\$ – Neil Jun 26 '18 at 14:25
  • \$\begingroup\$ @Neil Thanks for the ⊗÷ι², but what would the changes be for printing a \n before the #s? The spiral is incorrect if I add the Print("\n"). \$\endgroup\$ – Kevin Cruijssen Jun 26 '18 at 14:40
  • \$\begingroup\$ Because the arms now overlap you need to make them an extra # longer. \$\endgroup\$ – Neil Jun 26 '18 at 14:43
3
\$\begingroup\$

Python 2, 179 178 bytes

thanks to Kevin Cruijssen for -1 byte.

n=input()
S,H=' #'
m=[S*n]*(n%2-~n)
x=n/4*2
y=0--n/4*2
k=2
m[y]=S*x+H+S*n
M=[1,0,-1,0]*n
exec'exec k/2*2*"x+=M[~k];y+=M[k];m[y]=m[y][:x]+H+m[y][x+1:];";k+=1;'*n
print'\n'.join(m)

Try it online!


Python 2, 179 bytes

In this approach formulas are used for x and y deltas instead of a lookup list.

n=input()
S,H=' #'
m=[S*n]*(n%2-~n)
x=n/4*2
y=0--n/4*2
k=2
m[y]=S*x+H+S*n
exec'exec k/2*2*"x+=k%-2+k%4/3*2;y-=(k%2or k%4)-1;m[y]=m[y][:x]+H+m[y][x+1:];";k+=1;'*n
print'\n'.join(m)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ n+1+n%2 to n%2-~n for -1 byte. And I need to remember 0--n/4*2 being 1 shorter than -(-n/4*2). Nice answer, +1 from me. \$\endgroup\$ – Kevin Cruijssen Jun 26 '18 at 15:17
1
\$\begingroup\$

JavaScript (ES6), 185 bytes

Sure this can be golfed more, maybe with currying, but here's my very humble attempt. Line breaks added for readability except penultimate character

r=(a,n=1)=>n?r(a.reduce((_,c)=>c).map((_,i)=>a.map(e=>e[i])).reverse(),n-1):a,
s=n=>n?r(s(n-1)).map((r,i)=>[...r,w,w].map(x=>i?x:'#')):[[w=' ']],
d=n=>r(s(n),1-i).map(r=>r.join``).join`
`

Usage: d(10) returns a string as per the N=10 challenge example.

Defines a function r(a,n) to rotate an array a by n turns; a function s(n) to generate a 2-dimensional array representing a spiral of size n by recursively rotating and adding spacing and lines (not rotated back to starting position); and a function d(n) to draw a spiral of size n, rotated consistently as per the challenge, and rendered as a returned string.

This was a really fun challenge :¬)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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