¡Letras, ponte en movimiento!

35

Dada una cadena, debe mover cada letra (a partir de la primera letra) por su posición en el alfabeto. Si llega al final de la cadena, debe envolverla. Las no letras no necesitan ser movidas.

Ejemplo:

Dog

Des la cuarta letra del alfabeto, así que la movemos cuatro puntos a la derecha. Después de envolver, eso cambia la cadena a oDg. oes la letra 15, (15 mod 3) = 0, por lo que no se mueve. ges la séptima letra - (7 mod 3) = 1, por lo que la cadena se convierte goD.

hi*bye

  • hes la octava letra, muévala 8 puntos - hi*bye=>i*hbye
  • ies la novena letra, muévala 9 puntos - i*hbye=>*hbiye
  • bes la segunda letra, muévela 2 puntos - *hbiye=>*hiybe
  • yes la letra 25, muévela 25 puntos - *hiybe=>*hibye
  • ees la quinta letra, muévela 5 puntos - *hibye=>*hibey

No es necesario mover las letras, pero aún así ocupan espacio.

  • cat => tca
  • F.U.N => .F.NU
  • mississippi => msiisppssii
geokavel
fuente
¿Tenemos que hacer un programa independiente o una función es suficiente? Además, ¿tenemos que imprimir la cadena?
Katenkyo
¿Qué caracteres pueden aparecer en la entrada? ASCII imprimible? ¿Saltos de línea? Cualquier ASCII? Cualquier Unicode?
Martin Ender
3
También un caso de prueba con letras repetidas sería bueno.
Martin Ender
@ Martin Cualquier ASCII.
geokavel
La función @Katenkyo está permitida. Si está utilizando una función, la salida es el valor de retorno.
geokavel

Respuestas:

6

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*byeejemplo. 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. :)

Martin Ender
fuente
Pyth necesita una lista de cortes en la lista.
isaacg
@isaacg Nah, estoy seguro de que no. ;)
Martin Ender
¿Podría hacerlo para que sea compatible con cadenas de varias líneas?
geokavel
@geokavel Oh claro, arreglado.
Martin Ender
El sith está contento, Darth Büttner.
geokavel
4

Ruby 125130132139 bytes

->q{a=q.chars.map{|c|[c,c=~/[a-z]/i&&c.ord%32]}
while i=a.index{|c,s|s}
c,s=a.delete_at i
a.insert (i+s)%q.size,[c]
end
a*''}

Demostración en línea con pruebas: http://ideone.com/GYJm2u

La inicial (versión sin golf): http://ideone.com/gTNvWY

Editar: ¡ Muchas gracias a manatwork por sus sugerencias!

Edición 2 : recuento de caracteres fijo (inicialmente estaba contando las terminaciones de línea CRLF).

Cristian Lupascu
fuente
Apenas probado: c.upcase.ord-64c.ord%32.
manatwork
@manatwork Eso funciona bien, gracias!
Cristian Lupascu
Mirando de nuevo ... ¡Espera! a.join??? ¿Quién eres y qué has hecho con w0lf? Ciertamente lo escribiría como a*''.
manatwork
@manatwork :) Estaba tan molesto por tener un while ... endcódigo en mi código que olvidé hacerlo. ¡Gracias por notarlo!
Cristian Lupascu
¿no puede a su vez que while ... enden (...)while ...?
Martin Ender
3

Python 3, 278 275 273 270 260 258 249 248 243 238 bytes

Realmente debería jugar mejor este golf, pero esta es mi solución, gracias a katenkyo por su ayuda con la lógica, y a Cyoce y Mego por su ayuda con el golf.

Editar: Por fin, lo reduje a una declaración de comparación. ¡CORTEJAR! (Y sí, podría mover eso z=-za a,m=m,abit, pero eso no ahorra bytes y confunde el código más de lo que pensé que era necesario)

Editar: el recuento de bytes estaba desactivado.

def m(s):
 l=len(s);r=range(l);p=[[i,s[i]]for i in r]
 for i in r:
  if s[i].isalpha():
   a=p[i][0];p[i][0]=m=(a+ord(s[i])%32)%l;z=1
   if a>m:a,m=m,a;z=-z
   for j in r:p[j][0]-=z*(j!=i)*(a<=p[j][0]<=m) 
 return''.join(dict(p).values())

Sin golf:

def move(string):
 length = len(string)
 places = [[i,string[i]]for i in range(length)]
 for index in range(length):
  char = string[index]
  if char.isalpha():
   a = places[index][0]
   mov = (a + ord(char)%32) % length
   places[index][0] = mov
   for j in range(length):
    k = places[j][0]
    if a <= k <= mov and j!=index:
     places[j][0]-=1
    elif mov <= k <= a and j != index:
     places[j][0]+=1
 return''.join(dict(places).values())
Sherlock9
fuente
Yo creo * * que p[j][0]puede ser reducido mediante el establecimiento J=p[j];al inicio, a continuación, sustituyendo las instancias de p[j][0]conP[0]
Cyoce
@Cyoce Creo que el problema es que necesito editar pdirectamente, y no una variable que se le haya p[j]asignado. Además, si miras mi historial de revisiones, tuve una variable k = p[j][0]para las a<=k<=mcomparaciones, pero resultó que la eliminación kfue mejor porque guardé más bytes en sangrías de la línea extra para establecer kde lo que guardé usando k.
Sherlock9