Apakah mungkin untuk menulis fungsi reverse string umum yang berfungsi untuk semua lokalisasi dan tipe string?

16

Saya hanya menonton presentasi Jon Skeet (dengan Tony the Pony) dari Dev-Days.

Meskipun "menulis fungsi string terbalik" adalah coding wawancara 101 - Saya tidak yakin itu benar-benar mungkin untuk menulis fungsi string terbalik umum, tentu saja bukan yang bekerja di semua lokalisasi dan semua jenis string.

Selain mendeteksi jika string input adalah ascii, UTF8, UTF16 (panjang tetap dan variabel) dll.
Ada kode 'terapkan aksen ke karakter berikutnya' (U + 0301) yang disorot oleh Jon. Kemudian ada ligatur yang mungkin ditampilkan atau tidak, atau dikodekan sebagai karakter ganda.

Tampaknya "membalikkan string" sebenarnya adalah salah satu tugas ilmu komputer yang lebih sulit!

Martin Beckett
sumber
Nah, coba hentikan masalah untuk sesuatu yang salah langkah tetapi lebih mudah dijelaskan kepada orang-orang.
JB King
Menjadi pertanyaan yang tidak subyektif dan teknis, saya berani mengatakan ini akan lebih cocok di StackOverflow (tolong jangan posting ulang di sana, itu akan diotomatisasi jika cukup banyak orang memilih untuk menutupnya di sini).
Péter Török
1
Tergantung pada bahasa pemrograman. Sebagai contoh di Ruby semudah "stressed".reverse: p
Marcelo
Pertanyaan filosofis yang hebat. FWIW, StringBuilder Java mendapatkan pengganti yang benar tetapi tidak dengan kombinasi
kdgregory
2
"Balikkan string ini menggunakan Java" adalah pertanyaan jebakan yang bagus. :)
Scott C Wilson

Jawaban:

5

Iya. Jika kita mendapatkan string, kita dapat membalik setiap karakter.

Masalahnya seperti yang ditunjukkan oleh Jon adalah apakah pembalikan itu masuk akal dan apakah itu sesuai dengan aturan bahasa, budaya, dan pengkodean. Air menjadi keruh semakin dalam Anda pergi.

Jika Anda melakukan segala jenis manipulasi string dalam C # menggunakan budaya Invarian saat menulis dan membaca, dengan cara itu Anda dapat memanipulasi mereka dengan aman. Jika tidak, bersiaplah untuk kegagalan panggilan dukungan Turki.

ToUpper () terlihat sangat polos, tetapi ini adalah epik yang gagal menunggu untuk terjadi.

Jon Raynor
sumber
2
Pertanyaan lainnya adalah - untuk apa orang menggunakan string reverse (selain wawancara Q)? Saya hanya pernah membutuhkannya untuk manipulasi buffer tingkat rendah dari port I / O - dan bahkan kemudian hampir tidak pernah benar-benar dengan string
Martin Beckett
@ Martin - Setuju. Mungkin untuk program bahasa Inggris mencari palidrom? Saya tidak berpikir saya telah menggunakannya selain memecahkan pertanyaan kuis.
Jon Raynor
@ Martin benar. Saya pikir itu hanya dilakukan secara ironis. :)
Scott C Wilson
2

Secara umum, ketika pertanyaan ini diajukan, ia mengasumsikan US-ASCII. Intinya bukan untuk menguji pengetahuan orang tentang Unicode (meskipun ini akan menjadi tindak lanjut yang menarik), seperti untuk melihat apakah mereka memahami cara kerja pointer. Sejumlah orang yang mengejutkan tidak dapat melakukan aritmatika penunjuk seperti ini.

Scott C Wilson
sumber
2
"Bagaimana ini bisa gagal dengan unicode?" adalah pertanyaan lanjutan yang bagus
Martin Beckett
Bagus tapi mungkin agak maju - lagipula, "balikkan string ini di tempat" adalah pertanyaan wawancara tingkat pemula. Anda mungkin tidak akan meminta orang yang berpengalaman sesuatu sesederhana ini, kecuali mungkin mereka sangat pemalu dan Anda mencoba menghangatkannya.
Scott C Wilson
1

Sebagai pertanyaan wawancara, biasanya ditanyakan tentang bit teknis melakukan in-place swap item 8-bit untuk membalikkan pesanan mereka (terlepas dari karakter apa yang sebenarnya mereka wakili).

Pada saat yang sama, terutama jika Anda mewawancarai orang yang relatif senior, Anda setidaknya bisa berharap untuk mendengar beberapa pertanyaan tentang spesifikasi dan bentuk input yang tepat. Bahkan jika Anda mengarahkan mereka kembali ke kasus sederhana dengan hanya bertukar item 8-bit, mengetahui apakah mereka berpikir secara lebih luas atau lebih dari itu mungkin berharga.

Jika Anda harus berurusan dengan berbagai input, Anda hanya perlu berpikir tentang "tumpukan", sedikit seperti tumpukan jaringan. Anda harus membangun perangkat lunak Anda dalam sejumlah lapisan, yang masing-masingnya menerapkan serangkaian transformasi yang cukup spesifik dalam urutan tertentu. Ini memungkinkan Anda menjaga setiap bagian dari transformasi cukup sederhana sehingga Anda dapat mengendalikannya, dan memiliki peluang yang masuk akal untuk membuatnya memenuhi persyaratannya.

Saya akan menguraikan satu kemungkinan yang saya temukan paling tidak bisa diterapkan. Saya yang pertama mengakui bahwa mungkin ada orang lain yang memiliki ide yang lebih baik. Setidaknya bagi saya, ini agak mirip rekayasa kasar, dengan sedikit keanggunan nyata.

Anda biasanya ingin memulai dengan mengonversi representasi lain ke UCS-4 (alias UTF-32). Untuk ini, Anda biasanya lebih suka mengandalkan input dari pengguna daripada mencoba untuk mengetahuinya sendiri. Dalam beberapa kasus, Anda dapat yakin bahwa urutan oktet tertentu tidak mengikuti aturan skema penyandian tertentu, tetapi Anda jarang (jika pernah) yakin bahwa ia mengikuti skema penyandian tertentu.

Langkah selanjutnya adalah opsional. Anda dapat menormalkan input ke salah satu dari empat bentuk normalisasi Unicode. Dalam hal ini, Anda mungkin ingin menerapkan transformasi "NFKC": dekomposisi kompatibilitas diikuti oleh komposisi kanonik. Ini akan (jika mungkin) mengubah menggabungkan bentuk diakritik (seperti U + 301 yang disebutkan Jon) menjadi titik kode tunggal (misalnya, "A" dengan "U + 301" akan dikonversi menjadi "Modal Latin A dengan akut" , U + 00C1).

Anda kemudian berjalan melalui semua karakter dari awal hingga akhir, memecah string menjadi karakter yang sebenarnya - dan jika ada (masih) menggabungkan tanda diakritik, menjaganya dengan karakter yang mereka modifikasi. Hasil dari ini biasanya akan menjadi indeks karakter aktual dalam string, seperti posisi dan panjang masing-masing.

Anda membalik urutan karakter lengkap itu, biasanya dengan menggunakan indeks yang Anda buat pada langkah sebelumnya.

Anda kemudian (lagi, secara opsional) menerapkan proses normalisasi Unicode lain, seperti NFD (dekomposisi kanonik). Ini akan mengubah "Latin A dengan akut" kembali menjadi dua poin kode - "modal Latin A" dan "menggabungkan Akut". Jika masukan Anda kebetulan mengandung U + 00C1 untuk memulai dengan, namun juga akan mengkonversi bahwa menjadi dua poin kode juga.

Anda kemudian mengkodekan urutan poin kode UCS-4 ke dalam pengkodean yang diinginkan (UTF-8, UTF-16, dll.)

Perhatikan bahwa langkah normalisasi Unicode dapat / akan mengubah jumlah titik kode yang diperlukan untuk menyimpan string, jadi jika Anda memasukkannya, Anda tidak dapat lagi merencanakan string hasil yang dimasukkan ke penyimpanan asli. Cukup jelas, poin kode yang dihasilkan mungkin tidak berhubungan langsung dengan poin kode input juga.

Jerry Coffin
sumber
Saya belum menemukan U + 301 sebelum Jon mengangkatnya. Saya tidak dapat melihat mengapa itu diperlukan dalam unicode dengan mesin terbang untuk semua karakter beraksen - Saya membayangkan itu kompatibilitas ke belakang
Martin Beckett
@ Martin: Sebenarnya ada cukup banyak kombinasi diakritik (seluruh rentang dari U + 0300 ke U + 036F, meskipun dari U + 0363 ke U + 036F yang usang terbaik). Karakter yang dikomposisi disediakan untuk beberapa kemungkinan yang paling umum, dan menggabungkan diakritik untuk hal lain yang diperlukan.
Jerry Coffin
Terlalu banyak penyimpanan ekstra, normalisasi, dan konversi. Ulangi saja karakter-karakternya, dan balikkan urutan unit kode konstituen di tempat. Kemudian balikkan urutan semua unit kode di tempat.
Deduplicator