CJam, 44 42 40 bytes
qN+ee_{Xa/~\+XW=eu__el=!\'@-*m<Xa+}fXWf=
A saída contém um avanço de linha à direita.
Teste aqui.
Explicação
Em vez de mover as letras pela sequência, removo repetidamente uma letra, giro a sequência de acordo e reinsiro a letra. Há um problema para fazer isso: precisamos ser capazes de distinguir o início da string do final da string (o que não podemos após uma simples rotação). É por isso que inserimos um avanço de linha no final como um guarda (letra antes do avanço de linha é o fim da string, letra depois do início). O bônus é que isso retorna automaticamente a sequência final para a rotação correta, onde o avanço de linha realmente está no final da sequência.
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.
Para ver por que isso acaba na posição correta, considere a última iteração do hi*bye
exemplo. Depois de processarmos o e
, a sequência enumerada fica nesta posição:
[[4 'y] [6 N] [2 '*] [0 'h] [1 'i] [3 'b] [5 'e]]
Primeiro, dividimos o avanço de linha e concatenamos as peças na ordem inversa:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y]]
O avanço de linha agora seria no início ou no final dessa sequência. Mas como o avanço de linha é apenas uma proteção que marca o final da sequência, isso significa que os caracteres estão na ordem correta. Agora, o avanço de linha não é uma letra, de modo que a matriz não é rotacionada. Assim, quando anexamos o avanço de linha, ele vai para onde ele pertence e tudo está na ordem que procuramos:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y] [6 N]]
Alguns resultados adicionais se alguém quiser comparar casos de teste mais longos:
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
Eu gosto desse último. :)