# Square-unspiral the string!

Given a string, first square it as follows:

First, write the string.

abcde


Next, write the string rotated one left.

abcde
bcdea


Keep doing this until you have written len(string) lines.

abcde
bcdea
cdeab
deabc
eabcd


Now, read from the string like this:

----+
+--+|
|+>||
|+-+|
+---+


Which gives:

abcdeabcdcbaedcbcdeabaede


Print this string.

### Test cases

abcdef -> abcdefabcdedcbafedcbcdefabcbafedefaf
cena! -> cena!cenanec!anena!cec!a!
ppcg -> ppcgppcppgcpcgpg
abc -> abcabacbc
ab -> abab
a -> a
->


Please comment if a test case is incorrect.

Remember, this is , so the code with the smallest number of bytes wins.

• cena! is wrong. It should match your example with abcde since both are 5 letters: cena!cenanec!anena!cec!a! Nov 3 '16 at 13:33
• @Linus Thank you, I have fixed it. Nov 3 '16 at 17:25

# JavaScript (ES7), 838078 77 bytes

s=>s.repeat(l=s.length).replace(/./g,_=>s[(c-=--i**.5-l&1||-1)%l],c=-1,i=l*l)


Bonus ES3-compliant program:

for(s=prompt(r=""),c=-1,l=s.length,i=l*l;i;)r+=s[(c-=l-Math.sqrt(i--)&1||-1)%l];alert(r)


## Explanation

This takes advantage of the fact that the output for e.g. a length 5 string can be represented as:

abcdeabcd cbaedcb cdeab aed e
012345678 7654321 23456 543 4


where each digit represents an index in the string (starting at 0), modulo the length of the string. In other words, if n is the length of the string, we increment the index 2n - 1 times, then decrement it 2(n - 1) - 1 times, then increment it 2(n - 2) - 1 times, etc. This can be simplified to the following algorithm:

• Start the index i at -1.
• For each integer x in the range [n2..1]:
• If floor(sqrt(x)) is of the same parity (even/odd) as n, increment i.
• Otherwise, decrement i.
• Add the character at index i mod n to the output.

This works because floor(sqrt(x)) switches parities after 2n - 1 iterations, then 2(n - 1) - 1 iterations, etc.

• Rediculous. Good Job!
– bren
Nov 4 '16 at 3:35

# Pyth, 15 bytes

.Wp.(H0_CZ.<LQU


A program that takes input of a "quoted string" and prints the result.

Try it online! or verify all test cases (modified for multiple input).

How it works

.Wp.(H0_CZ.<LQU  Program. Input: Q
L U  Map over [0, 1, 2, 3, ..., Q-1] (implicit input):
.< Q     Q left-shifted by that many characters
Call this X
.W               While
.(H0          popping the first element of X (mutates X in-place)
p              and printing it with no trailing newline is truthy:
Z           X =
C            X transposed
_             reversed


# Python 2.7 (in CMD.EXE), 91 bytes

This requires a terminal with a working backspace(\b), and will not work on repl.it or ideone.com. A print statement ending in a comma separates further output with space instead of a newline or return. The backspace allows us to overwrite the separating space.

s=input();r=s[::-1];n=len(s)-1;i=0
while i<=n:print'\b'+s[i:]+s[:n-i]+r[i+2:]+r[:n-i],;i+=2


# Python 2.7, 96 bytes

Try it on ideone.com or repl.it (thanks to Oliver). Input must be a python string, e.g.'cena!'.

s=input();r=s[::-1];n=len(s)-1;i=0;S=''
while i<=n:S+=s[i:]+s[:n-i]+r[i+2:]+r[:n-i];i+=2
print S


The four slices appended by the loop (s[i:],s[:n-i],r[i+2:],r[:n-i]) are taken from four edges of the spiral. For instance with 01234 the square is:

01234
12340
23401
34012
40123


So we take 01234,0123,210,4321. The variable i is the index of the top-left value in each step of the process. In the final spiral several of the slices may be empty.

• It's probably not the only save, but by changing to Python 3, getting rid of the S='', print S, and S+=, and wrapping everything before the i+=2 in a print() statement with sep='', you can save 2 bytes.
Nov 3 '16 at 16:58
• @Shebang I'm not following right off. Feel free to add a python 3 answer yourself. Nov 3 '16 at 17:03
• You can change i<=n to n>i Nov 4 '16 at 17:46
• It saves a byte. Nov 4 '16 at 18:45
• @Oliver, Thanks... but it does not work for "a string of odd length." Nov 4 '16 at 18:59

# Jelly, 11 10 bytes

ẋ2µṖȮṖUµÐL


### How?

The unspiralled square is a series of "top-edge plus right-edge" and "bottom-edge plus left-edge" runs, each of which is the reverse of the previous run without the first and last letter, and the first of which is the input plus the input without the last letter (e.g. input "abcde" has an output of "abcdeabcd" + "cbaedcb" + "cdeab" + "aed" + "e").

ẋ2µṖȮṖUµÐL - Main link: s                            e.g. abcde
ẋ2         - repeat s twice                          e.g. abcdeabcde
µ    µ   - monadic chain separation
ÐL - repeat until results are no longer unique:
Ṗ       -     remove the last character                abcdeabcd / cbaedcb / cdeab / aed / e   / ""
Ȯ      -     print z (with no linefeed) and return z
Ṗ     -     remove the last character                abcdeabc  / cbaedc  / cdea  / ae  / ""  / ""
U    -     reverse                                  cbaedcba  / cdeabc  / aedc  / ea  / ""  / "" <- no longer unique.



# 05AB1E, 12 bytes

2×[DõQ#¨D?¨R


Try it online!

Explanation:

 2×[DõQ#¨D?¨R
# Implicit input
2×            # Repeat twice
[           # Begin infinite loop
┏>  DõQ#       # If empty string, break
┃       ¨      # Remove last character
┃        D     # Duplicate
┃         ?    # Print with no newline and pop
┃          ¨   # Remove last character
┃           R  # Reverse
┗━━━━━━━━━━━━┛ # Implicit end infinite loop


# MATL, 27 bytes

"GX@q_YS]vGn1YL_GnoQ&Ple&S)


The empty input exits with an error (producing the correct output).

# C, 95 94 Bytes

i,j,k,l;f(char*s){for(k=-1,l=i=strlen(s);i--;)for(j=i*2;~j--;putchar(s[(k+=(l-i)%2*2-1)%l]));}


• Suggest l-i&1?1:-1 instead of (l-i)%2*2-1 Aug 4 '20 at 20:59

# Perl, 99 bytes

$_=<>; chop; @a=split//; print(@a[$%,(@f=1-($b=@a-$%)..$b-3),$b-1?$b-2:(),reverse@f]),$%+=2 until\$%>@a


Whitespace is not part of the program and is provided for readability.

Not extremely efficient code. I should be able to shorten the first three lines somehow, but everything I tried to do failed. That ternary operator also needs to be fixed somehow, but having it this way made it possible to shorten my code by like, 10 bytes because I could cut out so much.

The code works by compiling a list of palindromes, separated by even numbers, which represent the place values of the string to be pulled.

• You can use -F  which will replace line 1 and 3. Give the input with echo -n to remove the chop. (that should get you around 81 bytes)
Nov 4 '16 at 22:42

# Actually, 21 13 bytes

This algorithm is largely based on Jonathan Allan's Jelly answer. There are two ways to go about printing the result as one string. The approach used here duplicates an intermediate step and then adds it to a running total in register 1 (an empty string by default); ;╕ in the function, then ╛ at the end. The other approach is to duplicate an intermediate step, leave those duplicate steps on the stack, and sum them into one string at the end; ; in the function, then kΣ at the end.

Golfing suggestions welcome. Try it online!

2*dX;╕dXRY╛


Ungolfing

         Implicit input s.
2*       Push a string that repeats s two times.
...Y   Call the following function until there is no change from the last call
dX       Discard the last element. Call this new string m.
;╕       Duplicate m and add it to the running total in register 1.
dXR      Discard the last element again and reverse the string.
╛        Push the unspiralled string from register 1 to the stack.
Implicit return.


# Python 3, 59 bytes

x=input()*2
while x:x=x[:-1];print(x,end='');x=x[:-1][::-1]


repl.it

A direct port of my Jelly answer; only a full program taking input (rather than a function).
The print(x,end='') is a print statement which will not print the default newline.

# Python 3, 93 bytes

s=input();r,n,i=s[::-1],len(s)-1,0
while n-i:print(s[i:]+s[:n-i]+r[i+2:]+r[:n-i],end='');i+=2


Try it online!

• Rather than print(...,end=''), do print(end=s[i:]+s[:n-i]+r[i+2:]+r[:n-i] Nov 4 '16 at 19:05
• Anyway, this solution doesn't work for abcde, it's missing an e at the end. Nov 4 '16 at 19:06
• Try i<=n instead of n-i for your condition. Nov 4 '16 at 19:09