Listy, ruszaj się!

35

Biorąc pod uwagę ciąg, musisz przenieść każdą literę (zaczynając od pierwszej litery) o jej pozycję w alfabecie. Jeśli dojdziesz do końca sznurka, musisz się owinąć. Nie-litery nie muszą być przenoszone.

Przykład:

Dog

Djest czwartą literą alfabetu, więc przesuwamy ją o cztery miejsca w prawo. Po zawinięciu zmienia to ciąg na oDg. ojest 15. literą (15 mod 3) = 0, więc się nie porusza. gjest siódmą literą - (7 mod 3) = 1, więc ciąg staje się goD.

hi*bye

  • hjest ósmą literą, przesuń ją o 8 miejsc - hi*bye=>i*hbye
  • ijest 9 literą, przesuń ją o 9 miejsc - i*hbye=>*hbiye
  • bto druga litera, przesuń ją o 2 miejsca - *hbiye=>*hiybe
  • yjest 25. literą, przesuń ją o 25 miejsc - *hiybe=>*hibye
  • ejest piątą literą, przesuń ją o 5 miejsc - *hibye=>*hibey

Nie-litery nie muszą być przenoszone, ale wciąż zajmują miejsce.

  • cat => tca
  • F.U.N => .F.NU
  • mississippi => msiisppssii
geokavel
źródło
Czy musimy zrobić samodzielny program, czy wystarczy funkcja? Ponadto, czy musimy wydrukować ciąg?
Katenkyo
Jakie znaki mogą pojawić się na wejściu? ASCII do druku? Kanały? Jakieś ASCII? Jakieś Unicode?
Martin Ender
3
Również test z powtarzającymi się literami byłby dobry.
Martin Ender
@Martin Any ASCII.
geokavel
Funkcja @Katenkyo jest dozwolona. Jeśli używasz funkcji, wyjście jest wartością zwracaną.
geokavel

Odpowiedzi:

6

CJam, 44 42 40 bajtów

qN+ee_{Xa/~\+XW=eu__el=!\'@-*m<Xa+}fXWf=

Dane wyjściowe zawierają końcowe podawanie wiersza.

Sprawdź to tutaj.

Wyjaśnienie

Zamiast przesuwać litery po sznurku, wielokrotnie usuwam literę, odpowiednio obracam sznurek, a następnie wkładam ponownie literę. Jest jeden haczyk: musimy odróżnić początek łańcucha od końca łańcucha (czego nie możemy po zwykłym obrocie). Dlatego wstawiamy wysuw linii na końcu jako zabezpieczenie (litera przed wysuwem linii jest końcem ciągu, litera po nim jest początkiem). Dodatkową zaletą jest to, że automatycznie przywraca końcowy ciąg znaków do prawidłowego obrotu, w którym linia faktycznie znajduje się na końcu ciągu.

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.

Aby zobaczyć, dlaczego kończy się to na właściwej pozycji, rozważ ostatnią iterację hi*byeprzykładu. Po przetworzeniu ewyliczony ciąg znajduje się w tej pozycji:

[[4 'y] [6 N] [2 '*] [0 'h] [1 'i] [3 'b] [5 'e]]

Najpierw podzieliliśmy się wokół linii i konkatenowaliśmy części w odwrotnej kolejności:

[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y]]

Kanał będzie teraz na początku lub na końcu tego ciągu. Ale ponieważ linefeed jest tylko osłoną, która oznacza koniec łańcucha, oznacza to, że znaki są w odpowiedniej kolejności. Teraz linia nie jest literą, więc tablica nie jest w ogóle obracana. Tak więc, gdy dodamy linię, idzie ona tam, gdzie należy i wszystko jest w kolejności, w jakiej szukamy:

[[2 '*] [0 'h] [1 'i] [3 'b] [5 'e] [4 'y] [6 N]]

Niektóre dodatkowe wyniki, jeśli ktoś chce porównać dłuższe przypadki testowe:

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

Podoba mi się ten ostatni. :)

Martin Ender
źródło
Pyth potrzebuje listy przerywników na liście.
isaacg
@isaacg Nie, jestem pewien, że nie. ;)
Martin Ender
Czy możesz to zrobić, aby wspierało ciągi wielowierszowe?
geokavel
@geokavel No tak, naprawione.
Martin Ender
Sith jest zadowolony, Darth Büttner.
geokavel
4

Rubin 125 130 132 139 bajtów

->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*''}

Demo online z testami: http://ideone.com/GYJm2u

Pierwsza (wersja bez golfa): http://ideone.com/gTNvWY

Edycja: Wielkie podziękowania dla manatwork za jego sugestie!

Edycja 2 : naprawiono liczbę znaków (początkowo liczyłem zakończenia linii CRLF).

Cristian Lupascu
źródło
Ledwo przetestowane: c.upcase.ord-64c.ord%32.
manatwork
@manatwork To działa dobrze, dzięki!
Cristian Lupascu
Patrzę jeszcze raz… Czekaj! a.join??? Kim jesteś i co zrobiłeś z w0lf? Z pewnością napisałby to jako a*''.
manatwork
@manatwork :) Byłem tak zdenerwowany tym, while ... endże mam w swoim kodzie, że zapomniałem to zrobić. Dzięki za zauważenie!
Cristian Lupascu
nie można włączyć, że while ... endw (...)while ...?
Martin Ender
3

Python 3, 278 275 273 270 260 258 249 248 243 238 bajtów

Naprawdę powinienem lepiej zagrać w golfa, ale oto moje rozwiązanie, z podziękowaniami dla katenkyo za jego pomoc w logice oraz Cyoce i Mego za ich pomoc w grze w golfa.

Edycja: W końcu sprowadziłem to do jednego zestawienia porównawczego. ZABIEGAĆ! (I tak, mógłbym to przenieść z=-zna a,m=m,akawałki, ale to nie oszczędza bajtów i zamazało kod bardziej, niż uważałem za konieczne)

Edycja: liczba bajtów była wyłączona.

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

Nie golfowany:

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
źródło
* * I uwierzyć, że p[j][0]można zmniejszyć poprzez ustawienie J=p[j];na początku, a następnie zastąpienie wystąpień p[j][0]zP[0]
Cyoce
@Cyoce Myślę, że problem polega na tym, że muszę edytować pbezpośrednio, a nie zmienną, która ją p[j]przypisała. Ponadto, jeśli spojrzysz na moją historię zmian, miałem zmienną k = p[j][0]do a<=k<=mporównań, ale okazało się, że usuwanie kbyło lepsze, ponieważ zapisałem więcej bajtów na wcięciach z dodatkowej linii do ustawienia kniż zapisałem przy użyciu k.
Sherlock9,