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!
-
\$\begingroup\$ most editors will not allow printing out a string that long \$\endgroup\$t-clausen.dk– t-clausen.dk2016年08月31日 08:05:07 +00:00Commented Aug 31, 2016 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– Sherlock92016年08月31日 08:21:34 +00:00Commented Aug 31, 2016 at 8:21
-
\$\begingroup\$ Nice and tricky :-) \$\endgroup\$Joffan– Joffan2016年08月31日 21:27:14 +00:00Commented Aug 31, 2016 at 21:27
10 Answers 10
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 . 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.T function outputs letters upright to prevent them from rotating with the spiral. (削除ここまで)
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.
-
\$\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
95will change the tightness of the spiral, and changing the15will adjust the linear spacing of the letters. \$\endgroup\$GuitarPicker– GuitarPicker2016年09月01日 19:03:32 +00:00Commented Sep 1, 2016 at 19:03
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>
R, 46 or 51 bytes, depending on spacing
s=1:scan();plot(s*sin(s),s*cos(s),pch=letters)
(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):
-
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– Sherlock92016年09月02日 06:50:39 +00:00Commented Sep 2, 2016 at 6:50
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.
-
\$\begingroup\$ You can replace
if len(r[-1])==len(r[0]):r=list(zip(*r[::-1]))+[[]]withif len(r[-1])==len(r[0]):r=[*zip(*r[::-1]),[]]to save 5 bytes. \$\endgroup\$R. Kap– R. Kap2016年09月01日 01:37:15 +00:00Commented Sep 1, 2016 at 1:37 -
\$\begingroup\$ Since you only use
rangeonce, you can removeRto 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 userange(int(input())). \$\endgroup\$Sherlock9– Sherlock92016年09月02日 11:22:01 +00:00Commented Sep 2, 2016 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– Sherlock92016年09月02日 11:53:09 +00:00Commented Sep 2, 2016 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
nin this version. Either you need to useint(input())or wrap in back up in a function. \$\endgroup\$Sherlock9– Sherlock92016年09月03日 03:40:03 +00:00Commented Sep 3, 2016 at 3:40 -
\$\begingroup\$ 2 bytes from condensing the
forloop: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– Sherlock92016年09月13日 02:40:55 +00:00Commented Sep 13, 2016 at 2:40
MATL, (削除) 21 (削除ここまで) 18 bytes
X^Xk1YL1Y2y)wG>~*c
Input 0 exits with an error (which is allowed by default).
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
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)
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:
-
\$\begingroup\$ One byte from if you remove a space from the import:
from turtle import*and another from changing fromwhiletofor i in range(input())\$\endgroup\$Sherlock9– Sherlock92016年09月13日 02:39:05 +00:00Commented Sep 13, 2016 at 2:39
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.
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
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
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))
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]);
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";}