Cartas, mexa-se!

35

Dada uma string, você deve mover cada letra (a partir da primeira letra) pela sua posição no alfabeto. Se você chegar ao final da corda, você deve enrolar. Não letras não precisam ser movidas.

Exemplo:

Dog

Dé a quarta letra do alfabeto, então movemos quatro pontos para a direita. Depois de envolver, isso muda a string para oDg. oé a 15ª letra, (15 mod 3) = 0, para que não se mova. gé a sétima letra - (7 mod 3) = 1, então a string se torna goD.

hi*bye

  • hé a 8ª letra, mova 8 pontos - hi*bye=>i*hbye
  • ié a 9ª letra, mova-a 9 pontos - i*hbye=>*hbiye
  • bé a 2ª letra, mova-a 2 pontos - *hbiye=>*hiybe
  • yé a 25ª letra, mova-a 25 pontos - *hiybe=>*hibye
  • eé a quinta letra, mova-a 5 pontos - *hibye=>*hibey

As não letras não precisam ser movidas, mas ainda ocupam espaço.

  • cat => tca
  • F.U.N => .F.NU
  • mississippi => msiisppssii
geokavel
fonte
Temos que fazer um programa independente ou uma função é suficiente? Além disso, temos que imprimir a string?
precisa
Quais caracteres podem aparecer na entrada? ASCII imprimível? Linefeeds? Algum ASCII? Algum Unicode?
Martin Ender
3
Também seria bom um caso de teste com letras repetidas.
Martin Ender
@ Martin Qualquer ASCII.
perfil completo de geokavel
A função @Katenkyo é permitida. Se você estiver usando uma função, a saída será o valor de retorno.
precisa

Respostas:

6

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

Martin Ender
fonte
Pyth precisa de lista de chop na lista.
Isaacg
@isaacg Nah, tenho certeza que não. ;)
Martin Ender
Você poderia fazê-lo para suportar seqüências de várias linhas?
geokavel
@geokavel Oh certo, fixo.
Martin Ender
O sith está satisfeito, Darth Büttner.
geokavel
4

Ruby 125 130 132 139 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*''}

Demonstração on-line com testes: http://ideone.com/GYJm2u

A inicial (versão ungolfed): http://ideone.com/gTNvWY

Edit: Muito obrigado a manatwork por suas sugestões!

Edição 2 : contagem fixa de caracteres (eu estava inicialmente contando as terminações de linha CRLF.)

Cristian Lupascu
fonte
Apenas mal testado: c.upcase.ord-64c.ord%32.
manatwork
@manatwork Isso funciona bem, obrigado!
Cristian Lupascu
Olhando de novo ... Espere! a.join??? Quem é você e o que você fez com o w0lf? Ele certamente escreveria como a*''.
manatwork
@ manatwork :) Eu estava tão chateado por ter um while ... endno meu código que esqueci de fazer isso. Obrigado por perceber!
Cristian Lupascu
você não pode transformar isso while ... endem (...)while ...?
Martin Ender
3

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

Eu realmente deveria jogar isso melhor, mas aqui está a minha solução, graças a katenkyo por sua ajuda na lógica e a Cyoce e Mego por sua ajuda no golfe.

Edit: Finalmente, eu tenho isso para uma declaração de comparação. WOO! (E sim, eu poderia mudar isso z=-zpara a,m=m,abit, mas isso não salva bytes e atrapalhava o código mais do que eu pensava ser necessário)

Editar: a contagem de bytes estava desativada.

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())

Ungolfed:

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
fonte
Eu * acredito * que p[j][0]pode ser reduzido definindo J=p[j];no início e substituindo instâncias de p[j][0]por #P[0]
Cyoce 17/15/17
@ Cyoce Acho que o problema é que preciso editar pdiretamente, e não uma variável que tenha sido p[j]atribuída a ela. Além disso, se você olhar para o meu histórico de revisões, eu tinha uma variável k = p[j][0]para a<=k<=mcomparações, mas verificou-se que a queda kera melhor porque salvei mais bytes nos recuos da linha extra para definirk do que salvei usando k.
Sherlock9