22
\$\begingroup\$

Write a program or function that, when given n, will print a spiral n characters long made up of the Latin alphabet ABCDEFGHIJKLMNOPQRSTUVWXYZ repeated as needed. This spiral should run through the alphabet only forwards.

Related to Alphabet Spiral, though the spiral runs through the alphabet forwards and backwards, and the spiral is constant.

Test cases

4   AB
    DC

40   UVWXYZ
     TGHIJA
    NSFABKB
    MREDCLC
    LQPONMD
    KJIHGFE

0

10  GHIJ
    FAB
    EDC

1000    UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
        TGHIJKLMNOPQRSTUVWXYZABCDEFGHIJA
        SFABCDEFGHIJKLMNOPQRSTUVWXYZABKB
        REZCDEFGHIJKLMNOPQRSTUVWXYZABCLC
        QDYBMNOPQRSTUVWXYZABCDEFGHIJCDMD
        PCXALEFGHIJKLMNOPQRSTUVWXYZKDENE
        OBWZKDEFGHIJKLMNOPQRSTUVWXALEFOF
        NAVYJCDMNOPQRSTUVWXYZABCDYBMFGPG
        MZUXIBCLCDEFGHIJKLMNOPQREZCNGHQH
        LYTWHABKBABCDEFGHIJKLMNSFADOHIRI
        KXSVGZAJAZGHIJKLMNOPQROTGBEPIJSJ
        JWRUFYZIZYFUVWXYZABCDSPUHCFQJKTK
        IVQTEXYHYXETQRSTUVWXETQVIDGRKLUL
        HUPSDWXGXWDSPUVWXYZYFURWJEHSLMVM
        GTORCVWFWVCROTGHIJAZGVSXKFITMNWN
        FSNQBUVEVUBQNSFABKBAHWTYLGJUNOXO
        ERMPATUDUTAPMREDCLCBIXUZMHKVOPYP
        DQLOZSTCTSZOLQPONMDCJYVANILWPQZQ
        CPKNYRSBSRYNKJIHGFEDKZWBOJMXQRAR
        BOJMXQRARQXMLKJIHGFELAXCPKNYRSBS
        ANILWPQZQPWVUTSRQPONMBYDQLOZSTCT
        ZMHKVOPYPONMLKJIHGFEDCZERMPATUDU
        YLGJUNOXONMLKJIHGFEDCBAFSNQBUVEV
        XKFITMNWVUTSRQPONMLKJIHGTORCVWFW
        WJEHSLMLKJIHGFEDCBAZYXWVUPSDWXGX
        VIDGRKJIHGFEDCBAZYXWVUTSRQTEXYHY
        UHCFQPONMLKJIHGFEDCBAZYXWVUFYZIZ
        TGBEDCBAZYXWVUTSRQPONMLKJIHGZAJA
        SFAZYXWVUTSRQPONMLKJIHGFEDCBABKB
        REDCBAZYXWVUTSRQPONMLKJIHGFEDCLC
        QPONMLKJIHGFEDCBAZYXWVUTSRQPONMD
                                LKJIHGFE

Rules

  • Your input will be a non-negative integer 0 <= n <= 1000, but your code should theoretically handle any non-negative integer.
  • Your output format may be in any sane format, with delimiters if necessary.
  • Rotations and reflections are equivalent.
  • Your alphabet may be uppercase or lowercase.
  • The empty spaces in your spiral may be filled in with whatever non-alphabetic nulls you see fit.
  • The spiral itself may be in any shape you see fit. Rectangular spirals work best with ASCII solutions, but graphical solutions may be shorter with circular spirals.
  • Leading and trailing spaces and newlines are allowed.
  • This is code golf. The shortest answer in bytes (or equivalent) wins.

As always, if anything is unclear or incorrect, please let me know in the comments. Good luck and good golfing!

\$\endgroup\$
  • \$\begingroup\$ most editors will not allow printing out a string that long \$\endgroup\$ – t-clausen.dk Aug 31 '16 at 8:05
  • \$\begingroup\$ @t-clausen.dk I went with the standard signed 32-bit integer maximum. If you have a better suggestion for an upper bound, I'd be happy to edit it in. \$\endgroup\$ – Sherlock9 Aug 31 '16 at 8:21
  • \$\begingroup\$ Nice and tricky :-) \$\endgroup\$ – Joffan Aug 31 '16 at 21:27

10 Answers 10

12
\$\begingroup\$

Logo, 129 87 bytes

Graphical solution, implemented as function

This was built on Calormen.com's Logo interpreter. The S function takes the number of characters as a parameter and draws them in a spiral. The T function outputs letters upright to prevent them from rotating with the spiral.. I decided that it looked nicer (and golfed out 42 bytes) to omit correcting the letter orientation. I also tightened up the spacing which did not change the byte count. If you were to actually roll up an alphabet, it would look more like this anyway.

Updated Version (letters roll)

TO S:r
PU IF:r[REPEAT:r[LABEL CHAR((REPCOUNT-1)%26)+65
RT 99/SQRT(REPCOUNT)FD 12]]END

Invocation

Invoke as follows: S iterations

Sample output

S 1000

Sample output for 1000 iterations

Old Version (letters always upright)

TO T:l:h
RT:h
LABEL CHAR(:l%26)+65
LT:h
END
TO S:r
PU IF:r[REPEAT:r[T REPCOUNT-1 90-HEADING
RT 95/SQRT(REPCOUNT)FD 15]]END

Old output removed to save space. See it here.

\$\endgroup\$
  • \$\begingroup\$ Don't ask how I came up with the math. I tried searching for formulas online, but most solved the problem by keeping the turn angle constant and increasing the segment length, whereas I wanted to keep the segment length constant and change the angle. Trial and error seems to have led to a stable formula. Adjusting the 95 will change the tightness of the spiral, and changing the 15 will adjust the linear spacing of the letters. \$\endgroup\$ – GuitarPicker Sep 1 '16 at 19:03
9
\$\begingroup\$

Javascript (ES6), 203 201 bytes

n=>{for(a=[],i=d=k=z=0,p=526,j=1;i<n;){p+=[1,32,-1,-32][d&3];j--||(((z^=1)||k++),j=k,d++);(a[y=p>>5]=(a[y]||Array(32).fill` `))[p&31]=String.fromCharCode(65+(i++%26))}return a.map(r=>r.join``).join`
`}

Demo

The demo below should be preferably run in full page.

let f =

n=>{for(a=[],i=d=k=z=0,p=526,j=1;i<n;){p+=[1,32,-1,-32][d&3];j--||(((z^=1)||k++),j=k,d++);(a[y=p>>5]=(a[y]||Array(32).fill` `))[p&31]=String.fromCharCode(65+(i++%26))}return a.map(r=>r.join``).join`
`}

function draw(n) {
  document.getElementById('v').innerHTML = n;
  document.getElementById('o').innerHTML = f(n);
}
draw(500);
pre {font-size:10px}
<input type="range" min="1" max="1000" oninput="draw(this.value)" style="width:500px"><span id="v"></span><pre id="o"></pre>

\$\endgroup\$
7
\$\begingroup\$

R, 46 or 51 bytes, depending on spacing

s=1:scan();plot(s*sin(s),s*cos(s),pch=letters)

enter image description here

(updated version of plot: the gray spiral isn't plotted by default but I added it after to show that the letters indeed lie on a spiral.)

The spiral isn't of constant spacing, so I hope this is okay. If constant spacing is required, start with s=(1:scan())^.5 instead, and add 5 bytes to the total. Then the output is as below (n=150):

enter image description here

\$\endgroup\$
  • 3
    \$\begingroup\$ How you space your spiral is completely up to you. I do have two suggestions, though: 1) Keep the second spiral. It adds to your answer even if it's less golfy; 2) Can you draw a spiral line going through the letters in the image of your first spiral? Just to make the alphabet spiral clearer. \$\endgroup\$ – Sherlock9 Sep 2 '16 at 6:50
6
\$\begingroup\$

Python 3.5, 180 157 152 147 141 bytes

-6 due to Sherlock9

r=[[]]
for x in range(int(input())):
 r=len(r[-1])<len(r[0])and r or[*zip(*r[::-1]),[]];r[-1]+=[chr(x%26+65)]
print(*map(''.join,r),sep='\n')

-5 due to Kap.

R=range
def g(n):
 r=[[]]
 for x in R(n):
  if len(r[-1])==len(r[0]):r=[*zip(*r[::-1]),[]]
  r[-1]+=[chr(x%26+65)]
 print(*map(''.join,r),sep='\n')

Revised Solution, python 3.x:

R=range
def g(n):
 r=[[]]
 for x in R(n):
  if len(r[-1])==len(r[0]):r=list(zip(*r[::-1]))+[[]]
  r[-1]+=[chr(x%26+65)]
 print(*map(''.join,r),sep='\n')

Previous Solution:

R=range
def g(n):
 r=[]
 for x,f in zip(R(n),(j<1for i in R(n)for j in R(i//2+1))):
  if f:r=list(zip(*r[::-1]))+[[]]
  r[-1].append(chr(x%26+65))
 print(*map(''.join,r),sep='\n')

Explanation

r is a list of lists that holds the spiral. The basic idea is that new letters are added to the bottom row of the spiral (r[-1].append(chr(x%26+65))). When the bottom row is filled up, the spiral is rotated 90 clockwise and a new empty row is added to the bottom (r = list(zip(*r[::-1]))+[[]]).

The trick is to figure out when to rotate the spiral. In the first solution, the generator (j<1for i in R(n)for j in R(i//2+1)) produces a sequence of True/False values that tell when to rotate the spiral. In the revised solution, I changed the way r is initialized. Now when the length of the bottom row equals the length of the top row, the spiral needs to be rotated.

\$\endgroup\$
  • \$\begingroup\$ You can replace if len(r[-1])==len(r[0]):r=list(zip(*r[::-1]))+[[]] with if len(r[-1])==len(r[0]):r=[*zip(*r[::-1]),[]] to save 5 bytes. \$\endgroup\$ – R. Kap Sep 1 '16 at 1:37
  • \$\begingroup\$ Since you only use range once, you can remove R to save bytes. You can also save bytes by converting your answer to a full program, though to preserve the use of [*zip(*r[::-1]),[]], you'll need to use range(int(input())). \$\endgroup\$ – Sherlock9 Sep 2 '16 at 11:22
  • \$\begingroup\$ Also, for x in range(int(input())):r=len(r[-1])<len(r[0])and r or[*zip(*r[::-1]),[]];r[-1]+=[chr(x%26+65)] since you're checking when the last line is equal or greater to the first line. \$\endgroup\$ – Sherlock9 Sep 2 '16 at 11:53
  • \$\begingroup\$ Two things: 1) You can make the for loop one line long by separating the statements with semicolons; and 2) you haven't defined n in this version. Either you need to use int(input()) or wrap in back up in a function. \$\endgroup\$ – Sherlock9 Sep 3 '16 at 3:40
  • \$\begingroup\$ 2 bytes from condensing the for loop: for x in range(int(input())):r=len(r[-1])<len(r[0])and r or[*zip(*r[::-1]),[]];r[-1]+=[chr(x%26+65)] \$\endgroup\$ – Sherlock9 Sep 13 '16 at 2:40
5
\$\begingroup\$

MATL, 21 18 bytes

X^Xk1YL1Y2y)wG>~*c

Input 0 exits with an error (which is allowed by default).

Try it online!

Explanation

X^Xk   % Input n implicitly. Take square root and round up
1YL    % Square matrix of that size containing a spiral of numbers
1Y2    % Predefined literal: string "AB···YZ"
y      % Duplicate the spiral matrix onto the top
)      % Apply as an index inth the string. Gives 2D array of chars
w      % Swap: move copy of the spiral matrix to top
G>~    % Set entries that exceed the input to 0, and the rest to 1 
*      % Multiply. This makes unwanted entries equal to 0
c      % Convert to char. 0 is shown as a space. Display implicitly
\$\endgroup\$
5
\$\begingroup\$

Python 2, 84 82 bytes

I'm using Turtle again. It's so fun! :D

from turtle import*
up()
for i in range(input()):write(chr(i%26+65));rt(9);fd(9+i)

Try it online

Unfortunately, Trinket.io has a horribly small canvas. I changed 9+i to 9+i/9 and adjusted the turtle's starting point for the purpose of screen-capturing this image, so that more of the output would fit:

output

\$\endgroup\$
  • \$\begingroup\$ One byte from if you remove a space from the import: from turtle import* and another from changing from while to for i in range(input()) \$\endgroup\$ – Sherlock9 Sep 13 '16 at 2:39
4
\$\begingroup\$

Pyth, 32 bytes

JS@Q2ju+.t_G)Hc<*GQQ.u+NY.iJJZ]Y

A program that prints a rectangular lower-case ASCII spiral. Depending on the input, one row or column of leading or trailing whitespace may be present.

Try it online

How it works

JS@Q2ju+.t_G)Hc<*GQQ.u+NY.iJJZ]Y  Program. Input: Q
  @Q2                             Yield sqrt(Q)
JS                                Unary range, J=[1, 2, 3, ..., floor(sqrt(q))]
                         .iJJ     Interleave J with itself, yielding [1, 1, 2, 2, 3, 3, ...
                                  floor(sqrt(Q)), floor(sqrt(Q))]
                    .u+NY    Z    Cumulatively reduce by addition with base case 0,
                                  yielding [0, 1, 2, 4, 6, 9, 12, 16, 20...]
                *GQ               Repeat the lower-case alphabet Q times
               <   Q              Truncate to legth Q
              c                   Split the above at the indices in the above list
      u                       ]Y  Reduce the above, with base case [[]]:
          _G                       Reverse
        .t  )                      Transpose
       +     H                     Add the next arm of the spiral
     j                            Join on newlines and implicitly print
\$\endgroup\$
3
\$\begingroup\$

TSQL, 386 362 358 306 bytes

Please note that TSQL doesn't have a way to rotate text. This script is starting from A and calculating which direction the next letter should be placed. (right, down, left, left, left, up, up, right...)

The script can handle a maximum of 7744 letters.

Golfed:

DECLARE @z INT = 7744

DECLARE @ INT=2+SQRT(@z-1)DECLARE @o varchar(max)=REPLICATE(SPACE(@-1)+char(10),@-1);WITH C as(SELECT 0i,@/2a,@/2b UNION ALL SELECT i+1,a+z/2,b+z%2FROM(SELECT*,IIF(a>@/2*2-b,IIF(a<b,2,-1),IIF(a>b,-2,1))z FROM C)t WHERE i<@z-1)SELECT @o=STUFF(@o,@*a-@+b,1,char(i%26+65))FROM c OPTION(maxrecursion 0)PRINT @o

Ungolfed:

DECLARE @z INT = 7744

DECLARE @ INT=2+SQRT(@z-1)
DECLARE @o varchar(max)=REPLICATE(SPACE(@-1)+char(10),@-1)

;WITH C as
(
  SELECT
    0i,@/2a,@/2b
  UNION ALL
  SELECT
    i+1,a+z/2,b+z%2
    FROM 
      (SELECT*,
         IIF(a>@/2*2-b,
           IIF(a<b,2,-1),
             IIF(a>b,-2,1))z FROM C)t
  WHERE
    i<@z-1
)
SELECT 
  @o=STUFF(@o,@*a-@+b,1,char(i%26+65))
FROM c  
OPTION(maxrecursion 0)

PRINT @o

Fiddle

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

Python 2, 243 bytes

r=range(input())
a=[1j**int((4*i+1)**.5)for i in r]
b=[map(int,(-sum(a[:i]).real,sum(a[:i]).imag))for i in r]
c,d=zip(*b)
for i in range(min(c),max(c)+1):print''.join([i,j]in b and chr(b.index([i,j])%26+65)or' 'for j in range(min(d),max(d)+1))

Ideone it!

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

PHP, 219 bytes

for($q=ceil(sqrt($a=$argn))**2,$d=1,$x=$y=$w=0;$i<$q;$i++,${yx[$w%2]}+=[-1,1][$d&1],$i%$d?:$d+=$w++&1)$e[$c[]=$x-!($a&1)][$l[]=$y]=$i<$a?chr(65+$i%26):" ";for($k=min($c);$e[$k];print join($e[+$k++])."\n")ksort($e[+$k]);

Try it online!

PHP , 260 Bytes

Old version

for($y=$x=$d=$i=0;$i<$m=ceil(sqrt($n=$argv[1]))**2;$i++){$a[$y][$x]=$i<$n?chr($i%26+65):" ";$d=$y==$x&$y<1?0:(1-$y==$x&$x>0?1:($y==$x&$y>0?2:($y==-$x&$x<0?3:$d)));$d>2?$y--:($d>1?$x--:($d>0?$y++:$x++));}ksort($a);foreach($a as$r){ksort($r);echo join($r)."\n";}
\$\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.