# Spiral out the Alphabet!

Look at the following string. Notice a pattern?

ABEFNOPEFGH
DC G  Q   I
M  H  R   J
LKJI  S   K
D     T   L
C     U   M
BAZYXWV   N
E         O
D         P
C         Q
BAZYXWVUTSR


As some might have noticed, it's basically a spiral of the alphabet, where the distances between rows / columns are gradually increasing by 1 space / newline.

# Rigorous definition

• Let's have a counter c, which is initially 0.
• We write out the first c + 1 letters of the alphabet from left to right: A.
• Then, from top to bottom the next (c + 1)(c + 2)/2 letters (add B): AB.

• From left to right, the next (c + 1)(c + 2)/2 (add C):

AB
C

• And from bottom to top, the next c + 1 letters (add D):

AB
DC

• Reached the end of the cycle. Hence, let's increment c (which becomes 1). Then, it starts back from the first step, the only difference being that instead of using the first c + 1 letters of the alphabet, we use the next c + 1 letters, starting from the last element of this cycle (D in this case, so we continue with EFG...). When Z is reached, it cycles back from A.

Given an integer N (which is positive for 1-indexing or non-negative for 0-indexing), output the first N cycles of the spiral.

# Rules

• You can either use the lowercase or the uppercase alphabet, but your choice must be consistent (only use one of them, mixing is not allowed).

• You can take input and provide output through any of the standard methods, in any programming language, while noting that these loopholes are forbidden by default.

• Acceptable output formats: multiline string, a list of strings representing lines, a list containing multiple lists of characters, each representing one line, or anything else you find suitable. In case you don't choose the first format, it would be nice to include a pretty-print version of your code.

• This is , so the shortest code in bytes (in each language) which fulfils the requirements wins!

# Test cases

The input integer will be separated by its corresponding output through a newline, and the tests will be separated using dashes. Note that these are 1-indexed.

1

AB
DC

--------

2

ABEF
DC G
M  H
LKJI

--------

3

ABEFNOP
DC G  Q
M  H  R
LKJI  S
D     T
C     U
BAZYXWV

-------

4

ABEFNOPEFGH
DC G  Q   I
M  H  R   J
LKJI  S   K
D     T   L
C     U   M
BAZYXWV   N
E         O
D         P
C         Q
BAZYXWVUTSR

-------
5

ABEFNOPEFGHFGHIJ
DC G  Q   I    K
M  H  R   J    L
LKJI  S   K    M
D     T   L    N
C     U   M    O
BAZYXWV   N    P
E         O    Q
D         P    R
C         Q    S
BAZYXWVUTSR    T
R              U
Q              V
P              W
O              X
NMLKJIHGFEDCBAZY

------

6

ABEFNOPEFGHFGHIJSTUVWX
DC G  Q   I    K     Y
M  H  R   J    L     Z
LKJI  S   K    M     A
D     T   L    N     B
C     U   M    O     C
BAZYXWV   N    P     D
E         O    Q     E
D         P    R     F
C         Q    S     G
BAZYXWVUTSR    T     H
R              U     I
Q              V     J
P              W     K
O              X     L
NMLKJIHGFEDCBAZY     M
S                    N
R                    O
Q                    P
P                    Q
O                    R
NMLKJIHGFEDCBAZYXWVUTS

• The testcases should be n=1,2,3,5,6, I think. – TFeld Dec 1 '17 at 10:22

# Charcoal, 31 bytes

Ｆ⮌…⁰ＮＢ⁺²⊘×ι⁺³ι⭆α§α⁺λ÷×ι⊕×ι⁺⁹⊗ι⁶


Try it online! Link is to verbose version of code. Note: The deverbosifier outputs a trailing separator for some reason. Explanation:

Ｆ⮌…⁰ＮＢ


Draw boxes in reverse order of size (largest to smallest).

⁺²⊘×ι⁺³ι


Calculate the size of the box.

⭆α§α⁺λ


Draw the border of the box using a rotated alphabet.

÷×ι⊕×ι⁺⁹⊗ι⁶


Calculate the letter that would appear at the top left of the box (0-indexed).

# Python 2, 176 bytes

n=input()
k=n*-~n/2+1
a=eval([[' ']*k]*k)
x=y=z=0
for s in range(4*n+4):exec s/4*(s/4+1)/2*"if'!'>a[y][x]:a[y][x]=chr(z%26+65);z+=1\nx+=abs(2-s%4)-1;y+=s%2-s%4/3*2\n"
print a


Try it online!

## Explanation

We construct an empty array of spaces of the right size, then move over it like this, starting in the top-left corner:

• 1 step →, 1 step ↓, 1 step ←, 1 step ↑

• 3 steps →, 3 steps ↓, 3 steps ←, 3 steps ↑

• 6 steps →, 6 steps ↓, 6 steps ←, 6 steps ↑

• 10 steps →, 10 steps ↓, 10 steps ←, 10 steps ↑

Every time we find a blank cell, we put a letter there and cycle to the next letter in the alphabet.

In the code, s%4 is the direction (→↓←↑), and we step this many times:

TriangularNumber(s/4) = s/4*(s/4+1)/2.


## Golf opportunities

• Is there a shorter way to map s%4 to 1,0,-1,0 than abs(2-s%4)-1?

• Is there a shorter way to map s%4 to 0,1,0,-1 than s%2-s%4/3*2?

## Credits

• Mr. Xcoder saved a byte.
• +1 Wow, this is just brilliant. Took me a while to figure out how it works. I found a shorthand for 21/(s%4+3)%3-1: s%2-2*(s%4>2) (179 bytes). It might still be golfable though – Mr. Xcoder Dec 1 '17 at 15:39

# C,  305  281 bytes

Thanks to @Mr. Xcoder for saving four bytes!

#define L(x,y)l[x][y]=a++%26+65;
#define F for(
c,i,j,a,p;f(n){char**l=calloc(8,i=a=n*n*4);F;i--;memset(l[i],32,a))l[i]=malloc(a);F c=a=p=i=0;c<n;++c){F i=p;i<c+p+!c;)L(j=0,c+i++)F p=i;j<=-~c*(c+2)/2;)L(j++,c+i)F;c+i-1;)L(j-1,c+--i)F i=0;i<=c;)L(j+~i++,0)}F i=0;i<j;)puts(l[i++]);}


Try it online!

• First time I see a #define for for( (that actually saves bytes). +1 from me. :) – Kevin Cruijssen Dec 1 '17 at 15:01

# Python 2, 262260254 245 bytes

lambda n:[[[' ',chr(65+(4*(i<j)+sum((i<j)*8+2+I*[5,9][i<j]+sum(2*R(I))for I in R(S(i,j)-1))+[i+j,-i-j][i<j])%26)][max(i,j)==S(i,j)*-~S(i,j)/2or i*j<1]for i in R(1+n*-~n/2)]for j in R(1+n*-~n/2)]
R=range
S=lambda x,y:int((8*max(x,y)+1)**.5+.99)/2


Try it online!

New method with more maths!

Returns a list of char-lists.

Old version:

# Python 2, 322321308 298 bytes

R=range
n=input()
w=1+n*-~n/2;r=[w*[' ']for _ in R(w)];r[0][0]='A';l=R(1,w*w*9);c=lambda:chr(65+l.pop(0)%26)
for i in R(n+1):
w=1+i*-~i/2;W=w-i
for x in R(W,w):r[0][x]=c()
for y in R(1,w):r[y][w-1]=c()
for x in R(1,w):r[w-1][w+~x]=c()
for x in R(1,w-W):r[w+~x][0]=c()
for l in r:printl[2::5]


Try it online!

• @Mr.Xcoder Isn't just .49 sufficient enough in that case, or does it fail for very big inputs? – Kevin Cruijssen Dec 1 '17 at 14:40
• @KevinCruijssen Not sure, but this works for sure, 260 bytes. – Mr. Xcoder Dec 1 '17 at 14:42
• I don't know Python that well, but is it possible to make an inline-variable for i<j, since you are using it four times? – Kevin Cruijssen Dec 1 '17 at 14:48
• 245 bytes by golfing +1==1+ from my previous method – Mr. Xcoder Dec 1 '17 at 14:56

# Perl 5, 177 +2 (-nl) = 179 bytes

2 bytes saved thanks to Xcali

sub n{chr 65+$c++%26}@O=(n);while($,++<$_){$_.=$"x$,for@O;push@O,($"x length$O[0])x$,;$O[0]=~s/ /n/eg;s/ $/n/e for@O;1while$O[-1]=~s/.*\K /n/e;s/^ /n/e for reverse@O}print for@O


Try it online

• You can save a byte by using -1 instead of $#O. Also using $, instead of $n will let you remove the space before for in $_.=$"x$n for@O – Xcali Dec 1 '17 at 16:34
• thank you, i was looking for other improvements but could not find for the moment – Nahuel Fouilleul Dec 1 '17 at 16:45
• saved 2 more bytes changing regex s/ (?=\S)/n/e to s/.*\K /n/e – Nahuel Fouilleul Dec 1 '17 at 16:49

# APL (Dyalog Classic), 47 bytes

(⎕a⍴⍨≢i)@i⍴∘''⊃⌈/i←∪+\↓1⍪⊃⍪⌿(+\⍳⎕)⌿¨⊂⍪∘-⍨∘.≠⍨⍳2


Try it online!