Surat, Bergeraklah!

35

Diberikan string Anda harus memindahkan setiap huruf (mulai dari huruf pertama) dengan posisinya di alfabet. Jika Anda mencapai ujung tali, Anda harus membungkusnya. Non-surat tidak perlu dipindahkan.

Contoh:

Dog

Dadalah huruf keempat dalam alfabet jadi kami memindahkannya empat tempat ke kanan. Setelah membungkus, itu mengubah string ke oDg. oadalah huruf ke-15, (15 mod 3) = 0, sehingga tidak bergerak. gadalah huruf ke 7 - (7 mod 3) = 1, jadi string menjadi goD.

hi*bye

  • hadalah huruf ke 8, pindahkan 8 titik - hi*bye=>i*hbye
  • iadalah huruf ke-9, pindahkanlah 9 titik - i*hbye=>*hbiye
  • badalah huruf ke-2, pindahkan 2 tempat - *hbiye=>*hiybe
  • yadalah huruf ke 25, pindahkan 25 titik - *hiybe=>*hibye
  • eadalah huruf ke-5, pindahkan 5 tempat - *hibye=>*hibey

Non-huruf tidak perlu dipindahkan, tetapi masih membutuhkan ruang.

  • cat => tca
  • F.U.N => .F.NU
  • mississippi => msiisppssii
geokavel
sumber
Apakah kita harus melakukan program mandiri atau fungsi sudah cukup? Juga, apakah kita harus mencetak string?
Katenkyo
Karakter apa yang dapat muncul di input? Cetak ASCII? Umpan baris? Adakah ASCII? Ada Unicode?
Martin Ender
3
Juga test case dengan huruf yang diulang akan bagus.
Martin Ender
@ Martin Any ASCII.
geokavel
Fungsi @Katenkyo diizinkan. Jika Anda menggunakan fungsi, maka output adalah nilai balik.
geokavel

Jawaban:

6

CJam, 44 42 40 byte

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

Output berisi linefeed tambahan.

Uji di sini.

Penjelasan

Alih-alih memindahkan surat melalui string, saya berulang kali menghapus surat, memutar string yang sesuai, dan kemudian memasukkan kembali surat itu. Ada satu tangkapan untuk melakukan ini: kita harus bisa membedakan awal string dari ujung string (yang tidak bisa kita lakukan setelah rotasi sederhana). Itu sebabnya kami menyisipkan linefeed di bagian akhir sebagai penjaga (surat sebelum linefeed adalah akhir dari string, huruf setelah itu adalah awal). Bonus adalah bahwa ini secara otomatis mengembalikan string akhir rotasi yang benar mana linefeed sebenarnya adalah pada akhir string.

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.

Untuk melihat mengapa ini berakhir di posisi yang tepat, pertimbangkan iterasi terakhir dari hi*byecontoh. Setelah kami memproses e, string yang dihitung ada di posisi ini:

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

Pertama, kami membagi linefeed dan menggabungkan bagian-bagian dalam urutan terbalik:

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

Linefeed sekarang akan berada di awal atau di akhir string ini. Tetapi karena linefeed hanyalah penjaga yang menandai akhir string, ini berarti bahwa karakter sebenarnya dalam urutan yang benar. Sekarang linefeed bukan huruf, sehingga array tidak diputar sama sekali. Jadi, ketika kita menambahkan umpan baris, ia masuk ke tempatnya, dan semuanya dalam urutan yang kami cari:

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

Beberapa hasil tambahan jika seseorang ingin membandingkan kasus pengujian yang lebih lama:

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

Saya suka yang terakhir. :)

Martin Ender
sumber
Pyth membutuhkan daftar chop pada daftar.
isaacg
@isaacg Nah, saya yakin tidak. ;)
Martin Ender
Bisakah Anda membuatnya sehingga mendukung string multi-line?
geokavel
@geokavel Oh benar, sudah pasti.
Martin Ender
Sith senang, Darth Büttner.
geokavel
4

Ruby 125 130 132 139 139 byte

->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 dengan tes: http://ideone.com/GYJm2u

Awal (versi yang tidak disatukan): http://ideone.com/gTNvWY

Sunting: Terima kasih banyak untuk manatwork atas sarannya!

Sunting 2 : jumlah karakter tetap (saya awalnya menghitung akhir baris CRLF.)

Cristian Lupascu
sumber
Baru saja diuji: c.upcase.ord-64c.ord%32.
manatwork
@manatwork Itu bekerja dengan baik, terima kasih!
Cristian Lupascu
Mencari lagi ... Tunggu! a.join??? Siapa kamu dan apa yang telah kamu lakukan dengan w0lf? Dia pasti akan menuliskannya sebagai a*''.
manatwork
@manatwork :) Saya sangat kesal karena memiliki while ... endkode saya sehingga saya lupa melakukannya. Terima kasih telah memperhatikan!
Cristian Lupascu
tidak bisakah kau mengubahnya while ... endmenjadi (...)while ...?
Martin Ender
3

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

Saya harus benar-benar bermain golf ini lebih baik, tapi di sini adalah solusi saya, dengan terima kasih kepada katenkyo untuk bantuannya dengan logika, dan untuk Cyoce dan Mego atas bantuan mereka dengan golf.

Sunting: Akhirnya, saya sampai pada satu pernyataan perbandingan. MERAYU! (Dan ya, saya bisa memindahkannya z=-zke dalam a,m=m,abit, tetapi itu tidak menghemat byte dan itu mengacaukan kode lebih dari yang saya pikir perlu)

Sunting: Jumlah byte tidak aktif.

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

Tidak Disatukan:

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
sumber
Saya * percaya * yang p[j][0]dapat dikurangi dengan menetapkan J=p[j];di awal, kemudian mengganti contoh p[j][0]denganP[0]
Cyoce
@Cyoce Saya pikir masalahnya adalah saya perlu mengedit psecara langsung, dan bukan variabel yang p[j]ditugaskan untuk itu. Juga, jika Anda melihat riwayat revisi saya, saya memang memiliki variabel k = p[j][0]untuk a<=k<=mperbandingan, tetapi ternyata menjatuhkan klebih baik karena saya menyimpan lebih banyak byte pada indentasi dari garis ekstra untuk ditetapkan kdaripada yang saya simpan dengan menggunakan k.
Sherlock9