CJam, 44 42 40 bajtów
qN+ee_{Xa/~\+XW=eu__el=!\'@-*m<Xa+}fXWf=
Dane wyjściowe zawierają końcowe podawanie wiersza.
Sprawdź to tutaj.
Wyjaśnienie
Zamiast przesuwać litery po sznurku, wielokrotnie usuwam literę, odpowiednio obracam sznurek, a następnie wkładam ponownie literę. Jest jeden haczyk: musimy odróżnić początek łańcucha od końca łańcucha (czego nie możemy po zwykłym obrocie). Dlatego wstawiamy wysuw linii na końcu jako zabezpieczenie (litera przed wysuwem linii jest końcem ciągu, litera po nim jest początkiem). Dodatkową zaletą jest to, że automatycznie przywraca końcowy ciąg znaków do prawidłowego obrotu, w którym linia faktycznie znajduje się na końcu ciągu.
lN+ e# Read input and append a linefeed.
ee e# Enumerate the array, so input "bob" would become [[0 'b] [1 'o] [2 'b] [3 N]]
e# This is so that we can distinguish repeated occurrences of one letter.
_{ e# Duplicate. Then for each element X in the copy...
Xa/ e# Split the enumerated string around X.
~ e# Dump the two halves onto the stack.
\+ e# Concatenate them in reverse order. This is equivalent to rotating the current
e# character to the front and then removing it.
XW= e# Get the character from X.
eu e# Convert to upper case.
_ e# Duplicate.
_el=! e# Check that convert to lower case changes the character (to ensure we have a
e# letter).
\'@- e# Swap with the other upper-case copy and subtract '@, turning letters into 1 to
e# 26 (and everything else into junk).
* e# Multiply with whether it's a letter or not to turn said junk into 0 (that means
e# everything which is not a letter will be moved by 0 places).
m< e# Rotate the string to the left that many times.
Xa+ e# Append X to the rotated string.
}fX
Wf= e# Extract the character from each pair in the enumerated array.
Aby zobaczyć, dlaczego kończy się to na właściwej pozycji, rozważ ostatnią iterację hi*bye
przykładu. Po przetworzeniu e
wyliczony ciąg znajduje się w tej pozycji:
[[4 'y] [6 N] [2 '*] [0 'h] [1 'i] [3 'b] [5 'e]]
Najpierw podzieliliśmy się wokół linii i konkatenowaliśmy części w odwrotnej kolejności:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y]]
Kanał będzie teraz na początku lub na końcu tego ciągu. Ale ponieważ linefeed jest tylko osłoną, która oznacza koniec łańcucha, oznacza to, że znaki są w odpowiedniej kolejności. Teraz linia nie jest literą, więc tablica nie jest w ogóle obracana. Tak więc, gdy dodamy linię, idzie ona tam, gdzie należy i wszystko jest w kolejności, w jakiej szukamy:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y] [6 N]]
Niektóre dodatkowe wyniki, jeśli ktoś chce porównać dłuższe przypadki testowe:
Hello, World!
,W oeHlo!lrld
Programming Puzzles & Code Golf
ago fgliPomomnrr elP& uC dezzsG
The quick brown fox jumps over the lazy dog
t eg chbi ko qfTounyzrj omw epx ueoahs rlvd
abcdefghijklmnopqrstuvwxyz
aqbrcdsetfguhivjwklxmnyozp
zyxwvutsrqponmlkjihgfedcba
abcdefghijklmnopqrstuvwxyz
Podoba mi się ten ostatni. :)