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 code-golf, so the code with the smallest number of bytes wins.
11 Answers 11
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.
-
1\$\begingroup\$ Rediculous. Good Job! \$\endgroup\$bren– bren2016年11月04日 03:35:54 +00:00Commented Nov 4, 2016 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.
-
\$\begingroup\$ It's probably not the only save, but by changing to Python 3, getting rid of the
S=''
,print S
, andS+=
, and wrapping everything before thei+=2
in aprint()
statement withsep=''
, you can save 2 bytes. \$\endgroup\$Kade– Kade2016年11月03日 16:58:04 +00:00Commented 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– Linus2016年11月03日 17:03:47 +00:00Commented Nov 3, 2016 at 17:03
-
\$\begingroup\$ You can change
i<=n
ton>i
\$\endgroup\$Oliver Ni– Oliver Ni2016年11月04日 17:46:08 +00:00Commented Nov 4, 2016 at 17:46 -
\$\begingroup\$ It saves a byte. \$\endgroup\$Oliver Ni– Oliver Ni2016年11月04日 18:45:36 +00:00Commented Nov 4, 2016 at 18:45
-
\$\begingroup\$ @Oliver, Thanks... but it does not work for
"a string of odd length."
\$\endgroup\$Linus– Linus2016年11月04日 18:59:44 +00:00Commented Nov 4, 2016 at 18:59
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.
05AB1E, 12 bytes
×ばつ[DõQ# ̈D? ̈R
Explanation:
×ばつ[DõQ# ̈D? ̈R
# Implicit input
×ばつ # 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]));}
Inspired by @ETHproductions answer.
-
\$\begingroup\$ Suggest
l-i&1?1:-1
instead of(l-i)%2*2-1
\$\endgroup\$ceilingcat– ceilingcat2020年08月04日 20:59:00 +00:00Commented Aug 4, 2020 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.
-
\$\begingroup\$ You can use
-F
which will replace line 1 and 3. Give the input withecho -n
to remove thechop
. (that should get you around 81 bytes) \$\endgroup\$Dada– Dada2016年11月04日 22:42:16 +00:00Commented Nov 4, 2016 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;╕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.
Python 3, 59 bytes
x=input()*2
while x:x=x[:-1];print(x,end='');x=x[:-1][::-1]
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
-
\$\begingroup\$ Rather than
print(...,end='')
, doprint(end=s[i:]+s[:n-i]+r[i+2:]+r[:n-i]
\$\endgroup\$FlipTack– FlipTack2016年11月04日 19:05:13 +00:00Commented Nov 4, 2016 at 19:05 -
1\$\begingroup\$ Anyway, this solution doesn't work for
abcde
, it's missing ane
at the end. \$\endgroup\$FlipTack– FlipTack2016年11月04日 19:06:41 +00:00Commented Nov 4, 2016 at 19:06 -
\$\begingroup\$ Try
i<=n
instead ofn-i
for your condition. \$\endgroup\$Linus– Linus2016年11月04日 19:09:38 +00:00Commented Nov 4, 2016 at 19:09
cena!
is wrong. It should match your example withabcde
since both are 5 letters:cena!cenanec!anena!cec!a!
\$\endgroup\$