CJam, 44 42 40 bytes
qN+ee_{Xa/~\+XW=eu__el=!\'@-*m<Xa+}fXWf=
La salida contiene un salto de línea final.
Pruébalo aquí.
Explicación
En lugar de mover las letras a través de la cadena, elimino repetidamente una letra, gire la cadena en consecuencia y luego vuelva a insertar la letra. Hay un inconveniente para hacer esto: necesitamos poder distinguir el comienzo de la cadena del final de la cadena (que no podemos después de una simple rotación). Es por eso que insertamos un salto de línea al final como protección (la letra antes del salto de línea es el final de la cadena, la letra después del comienzo). La ventaja es que esto devuelve automáticamente la cadena final a la rotación correcta donde el avance de línea está realmente al final de la cadena.
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 qué esto termina en la posición correcta, considere la última iteración del hi*bye
ejemplo. Después de procesar el e
, la cadena enumerada está en esta posición:
[[4 'y] [6 N] [2 '*] [0 'h] [1 'i] [3 'b] [5 'e]]
Primero, nos dividimos alrededor del salto de línea y concatenamos las partes en orden inverso:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y]]
El avance de línea ahora sería al principio o al final de esta cadena. Pero dado que el salto de línea es solo un protector que marca el final de la cadena, esto significa que los caracteres están realmente en el orden correcto. Ahora el salto de línea no es una letra, por lo que la matriz no gira en absoluto. Por lo tanto, cuando agregamos el salto de línea, va a donde pertenece, y todo está en el orden que estamos buscando:
[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y] [6 N]]
Algunos resultados adicionales si alguien quiere comparar casos de prueba más largos:
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
Me gusta ese último. :)