13
\$\begingroup\$

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.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ cena! is wrong. It should match your example with abcde since both are 5 letters: cena!cenanec!anena!cec!a! \$\endgroup\$
    – Linus
    Commented Nov 3, 2016 at 13:33
  • \$\begingroup\$ @Linus Thank you, I have fixed it. \$\endgroup\$
    – Oliver Ni
    Commented Nov 3, 2016 at 17:25

11 Answers 11

8
\$\begingroup\$

JavaScript (ES7), 83 80 78 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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Rediculous. Good Job! \$\endgroup\$
    – bren
    Commented Nov 4, 2016 at 3:35
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ 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. \$\endgroup\$
    – Kade
    Commented Nov 3, 2016 at 16:58
  • \$\begingroup\$ @Shebang I'm not following right off. Feel free to add a python 3 answer yourself. \$\endgroup\$
    – Linus
    Commented Nov 3, 2016 at 17:03
  • \$\begingroup\$ You can change i<=n to n>i \$\endgroup\$
    – Oliver Ni
    Commented Nov 4, 2016 at 17:46
  • \$\begingroup\$ It saves a byte. \$\endgroup\$
    – Oliver Ni
    Commented Nov 4, 2016 at 18:45
  • \$\begingroup\$ @Oliver, Thanks... but it does not work for "a string of odd length." \$\endgroup\$
    – Linus
    Commented Nov 4, 2016 at 18:59
1
\$\begingroup\$

Jelly, 11 10 bytes

ẋ2µṖȮṖUµÐL

TryItOnline!, or all tests

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.
        
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

MATL, 27 bytes

"GX@q_YS]vGn1YL_GnoQ&Ple&S)

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

Try it online! Or verify all test cases.

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

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]));}

Inspired by @ETHproductions answer.

\$\endgroup\$
1
  • \$\begingroup\$ Suggest l-i&1?1:-1 instead of (l-i)%2*2-1 \$\endgroup\$
    – ceilingcat
    Commented Aug 4, 2020 at 20:59
0
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ 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) \$\endgroup\$
    – Dada
    Commented Nov 4, 2016 at 22:42
0
\$\begingroup\$

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 at the end.

Golfing suggestions welcome. Try it online!

2*`dX;╕dXR`Y╛

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.
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
-1
\$\begingroup\$

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!

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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