CJam, 44 42 40 байт
qN+ee_{Xa/~\+XW=eu__el=!\'@-*m<Xa+}fXWf=
Вывод содержит завершающий перевод строки.
Проверьте это здесь.
объяснение
Вместо того, чтобы перемещать буквы по строке, я несколько раз удаляю буквы, поворачиваю строку соответственно, а затем снова вставляю буквы. Для этого есть одна загвоздка: нам нужно уметь отличать начало строки от конца строки (что мы не можем сделать после простого поворота). Вот почему мы вставляем перевод строки в конец как защитный символ (буква перед переводом строки является концом строки, буква после ее начала). Бонус в том, что это автоматически возвращает окончательную строку в правильное вращение, где перевод строки фактически находится в конце строки.
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.
Чтобы понять, почему это оказывается в правильном положении, рассмотрим последнюю итерацию hi*bye
примера. После того как мы обработали e
, перечисляемая строка находится в этой позиции:
[[4 'y] [6 N] [2 '*] [0 'h] [1 'i] [3 'b] [5 'e]]
Сначала мы разбиваем строку и объединяем части в обратном порядке:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y]]
Теперь перевод строки будет либо в начале, либо в конце этой строки. Но так как перевод строки является просто защитой, которая отмечает конец строки, это означает, что символы на самом деле в правильном порядке. Теперь перевод строки не является буквой, поэтому массив вообще не вращается. Таким образом, когда мы добавляем перевод строки, он идет туда, где он принадлежит, и все в том порядке, в котором мы ищем:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y] [6 N]]
Некоторые дополнительные результаты, если кто-то хочет сравнить более длинные тестовые случаи:
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
Мне нравится этот последний. :)