Tugas
- Anda diberi string yang dapat berubah yang cocok
[a-z]+( [a-z]+)*
. - Anda harus mengubahnya menjadi string yang berisi kata-kata yang sama, tetapi dalam urutan terbalik, sehingga "halo di sana semua orang" menjadi "semua orang di sana halo".
- Anda tidak diizinkan menggunakan lebih dari jumlah memori tambahan yang konstan (jadi jangan menyalin seluruh string atau keseluruhan kata ke dalam buffer yang baru saja Anda alokasikan).
- Tidak ada batasan waktu. Menjadi tidak efisien tanpa harapan tidak akan merugikan skor Anda.
- Jika bahasa pilihan Anda tidak mengizinkan mutasi string, array karakter adalah pengganti yang dapat diterima.
Nilai Anda
- Skor Anda dihitung murni pada jumlah tugas yang Anda buat untuk elemen string (skor kecil adalah yang terbaik). Jika Anda menggunakan fungsi pustaka yang menulis ke string, tulisannya juga dihitung.
- Misalkan jumlah tugas yang Anda butuhkan untuk input s adalah n (s) . Maka skor Anda adalah maksimum (pedantically, supremum) di atas semua input s (cocok dengan regex yang ditentukan di atas) dari n (s) / panjang (s) . Jika Anda tidak dapat menghitung ini dengan tepat, Anda dapat menggunakan batas atas terendah yang dapat Anda buktikan.
- Anda dapat memutus ikatan jika Anda dapat membuktikan bahwa algoritme Anda menggunakan penugasan yang asimptot lebih sedikit (ini dapat terjadi bahkan jika Anda memiliki skor yang sama, lihat di bawah). Jika Anda tidak dapat melakukan ini, Anda dapat memutuskan hubungan dengan menunjukkan bahwa Anda menggunakan lebih sedikit memori tambahan. Namun, kondisi tie-break pertama selalu diutamakan.
- Untuk beberapa input setiap karakter perlu diubah, jadi tidak mungkin untuk mencetak kurang dari 1.
- Saya dapat memikirkan algoritma sederhana dengan skor 2 (tapi saya tidak memasukinya).
Catatan tentang suprema dan ikatan
- Supremum satu set angka adalah angka terkecil yang tidak lebih kecil dari angka itu. Ini sangat mirip dengan set maksimum, kecuali bahwa beberapa set infinite seperti {2/3, 3/4, 4/5, 5/6, ...} tidak memiliki elemen maksimum tunggal, tetapi masih akan memiliki supremum, dalam hal ini 1.
- Jika Anda berhasil "menyimpan" hanya jumlah tugas yang konstan pada algoritme skor 2 saya (katakanlah), skor Anda akan tetap 2, karena Anda akan mendapatkan mendekati 2 sewenang-wenang semakin besar input yang Anda dapatkan. Namun, Anda menang pada tie-break jika itu yang terjadi.
code-challenge
Ben Millwood
sumber
sumber
little-omega(1)
ruang dengan meletakkannya di tumpukan.O(1)
ruang tambahan. Anda perluO(log n)
ruang untuk menyimpan posisi indeks, karena integer k-bit hanya dapat menyimpan di dalamnya untuk string panjang hingga2^k
. Membatasi panjang string membuat tantangan agak tidak ada gunanya, karena setiap algoritma akan membutuhkanO(1)
ruang dengan cara ini.Jawaban:
Python, Nilai:
21,51,25Ini adalah kombinasi langsung antara jawaban primo dan jawaban saya. Jadi kredit untuknya juga!
Buktinya masih dalam proses, tapi ini kode untuk bermain! Jika Anda dapat menemukan contoh balasan skor lebih besar dari 1,25 (atau jika ada bug), beri tahu saya!
Saat ini kasus terburuk adalah:
di mana ada persis n dari masing-masing huruf "a", "b", "c", dan "" (spasi), dan tepat dua "d" s. Panjang string adalah 4n + 2 dan jumlah tugas adalah 5n + 2 , memberikan skor 5/4 = 1,25 .
Algoritma ini bekerja dalam dua langkah:
k
itustring[k]
danstring[n-1-k]
merupakan batasan katastring[:k]+string[n-1-k:]
(yaitu, rangkaian karakter pertamak
dan terakhirk
) dengan modifikasi kecil.di mana
n
panjang tali.Peningkatan yang diberikan algoritma ini berasal dari "modifikasi kecil" pada Langkah 2. Pada dasarnya adalah pengetahuan bahwa dalam string gabungan, karakter pada posisi
k
dank+1
merupakan batas kata (yang berarti spasi atau karakter pertama / terakhir dalam sebuah kata), dan jadi kita bisa langsung mengganti karakter di posisik
dank+1
dengan karakter yang sesuai di string terakhir, menyimpan beberapa tugas. Ini menghapus kasus terburuk dari algoritma pembalikan kata hostAda kasus-kasus di mana kita tidak dapat menemukan itu
k
, dalam hal itu, kita hanya menjalankan "algoritma pembalikan kata" pada seluruh string.Kode ini panjang untuk menangani keempat kasus ini dalam menjalankan kata pembalikan algoritma pada string "concatenated":
k
tidak ditemukan (f_long = -2
)string[k] != ' ' and string[n-1-k] != ' '
(f_long = 0
)string[k] != ' ' and string[n-1-k] == ' '
(f_long = 1
)string[k] == ' ' and string[n-1-k] != ' '
(f_long = -1
)Saya yakin kode ini dapat dipersingkat. Saat ini lama karena saya tidak memiliki gambaran yang jelas tentang keseluruhan algoritma pada awalnya. Saya yakin orang dapat mendesainnya untuk diwakili dalam kode yang lebih pendek =)
Contoh dijalankan (pertama adalah milik saya, kedua adalah milik primo):
Anda dapat melihat bahwa skornya hampir sama, kecuali untuk kasus terburuk dari algoritma pembalikan kata host pada contoh ketiga, yang mana pendekatan saya menghasilkan skor kurang dari 1,25
Python, Nilai: 1,5
Jumlah tugas yang tepat dapat diperkirakan dengan rumus:
dengan kasus terburuk adalah:
dengan 55 tugas pada string dengan panjang 37.
Idenya mirip dengan yang saya sebelumnya, hanya saja dalam versi ini saya mencoba untuk menemukan awalan dan akhiran pada batas kata paling banyak 1. Lalu saya menjalankan algoritma saya sebelumnya pada awalan dan akhiran itu (bayangkan mereka digabungkan) . Kemudian lanjutkan pada bagian yang belum diproses.
Misalnya, untuk kasus terburuk sebelumnya:
pertama-tama kita akan melakukan pembalikan kata pada "ab" dan "c" (4 tugas) menjadi:
Kita tahu bahwa di perbatasan dulu ruang (ada banyak kasus yang harus ditangani, tetapi Anda bisa melakukannya), jadi kami tidak perlu menyandikan ruang di batas, ini adalah peningkatan utama dari algoritma sebelumnya .
Lalu akhirnya kita jalankan di empat karakter tengah untuk mendapatkan:
dalam total 8 tugas, optimal untuk kasus ini, karena semua 8 karakter berubah.
Ini menghilangkan kasus terburuk dalam algoritma sebelumnya karena kasus terburuk dalam algoritma sebelumnya dihilangkan.
Lihat beberapa contoh dijalankan (dan perbandingan dengan jawaban @ primo - ini adalah baris kedua):
jawaban primo umumnya lebih baik, walaupun dalam beberapa kasus saya dapat memiliki 1 poin keunggulan =)
Juga kodenya jauh lebih pendek daripada milikku, haha.
Python, Score: asymptotically 2, dalam kasus normal jauh lebih sedikit
kode lama dihapus karena kendala ruang
Idenya adalah untuk iterate melalui setiap indeks, dan untuk setiap indeks
i
, kita mengambil karakter, menghitung posisi baruj
, menghafal karakter pada posisij
, menetapkan karakter dii
untukj
, dan ulangi dengan karakter pada indeksj
. Karena kita memerlukan informasi ruang untuk menghitung posisi baru, saya menyandikan ruang lama sebagai versi huruf besar dari surat baru, dan ruang baru sebagai '@'.sumber
length(string)/3
dengan memaksa setiap kata dalam kasus terburuk setidaknya memiliki panjang 2), maka skor akan kurang dari 2 (dalam contoh di atas akan menjadi 1,67)if any(process_loop(...) for j in range(...))
Tidakkah tugas dari loop proses ini perlu dihitung?dry_run
parameternya diatur ke non-nol (nilai kei
). Di dalamprocess_loop
, jikadry_run
bukan nol, itu tidak akan melakukan tugas apa pun.Perl, skor 1.3̅
Untuk setiap karakter non-spasi satu tugas dilakukan, dan untuk masing-masing karakter spasi dua tugas.
Karena karakter spasi tidak dapat berjumlah lebih dari setengah jumlah total karakter, skor kasus terburuk adalah 1,5 .Algoritma tidak berubah, tetapi saya dapat membuktikan batas atas yang lebih rendah. Mari kita buat dua pengamatan:
Maka dapat dilihat bahwa 'kasus terburuk' teoretis dengan asimtotik 1/2 spasi sama sekali bukan kasus terburuk:
ab c d e f g h i ...
Sebenarnya, ini kasus yang cukup bagus.
Untuk mencegah pengamatan satu dan dua di atas, setiap kata satu karakter perlu direposisi ke tengah kata yang panjangnya tiga atau lebih karakter. Ini menyarankan kasus terburuk yang mengandung 1/3 spasi asimptotik:
a bcd a bcd a ... bc
Atau setara, hanya kata-kata dua karakter:
a bc de fg hi jk ...
Karena kasus terburuk berisi 1/3 spasi asimptot, skor kasus terburuk menjadi 1,3̅ .
Sunting: Menambahkan penghitung swap, dan rasionya.
Input diambil dari stdin. Penggunaan sampel:
metode
Untuk memulai, karakter pertama dari string dipindahkan ke tujuan akhirnya. Karakter yang baru diganti kemudian dipindahkan ke tujuannya, dll. Ini berlanjut sampai salah satu dari dua kondisi terpenuhi:
Ketika ini terjadi, karakter tidak ditukar dengan ruang, tetapi lebih ke posisi cermin ruang. Algoritma berlanjut dari posisi itu.
Ketika target kembali ke posisi awal awal dari siklus saat ini, karakter yang tidak ditukar berikutnya (atau lebih tepatnya, karakter yang tidak ditukar akan melakukan) perlu ditemukan. Untuk melakukan ini di bawah batasan memori konstan, semua swap yang telah dibuat sampai saat ini dilacak kembali.
Setelah fase ini, setiap karakter non-spasi telah dipindahkan paling banyak satu kali. Untuk menyelesaikan, semua karakter spasi ditukar dengan karakter di posisi cermin mereka, membutuhkan dua operasi penugasan per ruang.
sumber
Ruby, skor 2
Sebagai starter, algoritma yang sangat mendasar. Pertama membalik seluruh string dan kemudian membalikkan setiap kata dalam string lagi. Dalam kasus terburuk (satu kata, bahkan jumlah karakter) skor menjadi 2.
Pemakaian:
sumber
C ++: Skor 2
sumber
Rebol
Saya tidak jelas tentang penilaian untuk ini. Tidak ada tugas string langsung dalam kode ini. Semuanya ditangani oleh orang
reverse/part
yang melakukan pembalikan di dalam dan awalnya pada seluruh string.Beberapa detail pada kode:
Loop melalui string (
series
) hingga mencapaitail?
Pertama kali dalam loop melakukan kebalikan penuh dari string -
reverse/part series tail series
(yang sama denganreverse series
)Kemudian balikkan setiap kata yang ditemukan pada iterasi lebih lanjut -
reverse/part series find series space
Setelah kata habis ditemukan, lalu kembali
tail series
sehingga akan membalik kata terakhir dalam string -reverse/part series tail series
Rebol memungkinkan melintasi string melalui pointer internal . Anda dapat melihatnya di
series: next f
(pindahkan pointer ke spasi setelah mulai dari kata berikutnya) danseries: head series
(reset pointer kembali ke kepala).Lihat Seri untuk info lebih lanjut.
Contoh penggunaan di konsol Rebol:
sumber
C: Skor 2
Ini hanya membalik seluruh string sekali kemudian membalikkan setiap kata.
sumber
Python: skor 2
Hampir identik dengan algoritma Howard, tetapi melakukan langkah pembalikan secara terbalik (pertama membalik kata kemudian membalik seluruh string). Digunakan memori tambahan adalah 3 variabel byte-size:
i
,j
, dant
. Secara teknis,find
danlen
menggunakan beberapa variabel internal, tetapi mereka dapat dengan mudah digunakan kembalii
atauj
tanpa kehilangan fungsi.edit cepat: menghemat penugasan string dengan hanya bertukar ketika karakter berbeda, jadi saya bisa mengambil beberapa poin tambahan dari catatan # 2.
sumber
Batch
Saya akui tidak sepenuhnya memahami skor (saya pikir itu dua) .. tapi saya akan mengatakan - itu yang terjadi .
Input diambil sebagai nilai input standar pertama, dan karenanya perlu dikelilingi oleh tanda kutip -
panggilan:
script.bat "hello there everyone"
keluar:
everyone there hello
.Mungkin orang lain bisa menilai saya (dengan asumsi saya belum, dengan cara lain, mendiskualifikasi diri saya).
sumber
Javascript
Pemakaian:
Saya mendapatkan perasaan aneh saya melewatkan sesuatu ...
sumber