Itu adalah pertanyaan wawancara yang tidak bisa saya jawab:
Bagaimana cara memeriksa bahwa sebuah string adalah palindrome menggunakan ekspresi reguler?
ps Sudah ada pertanyaan " Bagaimana cara memeriksa apakah string yang diberikan adalah palindrome? " dan ini memberikan banyak jawaban dalam berbagai bahasa, tetapi tidak ada jawaban yang menggunakan ekspresi reguler.
regex
palindrome
Degvik
sumber
sumber
Jawaban:
Jawaban atas pertanyaan ini adalah "tidak mungkin". Lebih khusus lagi, pewawancara bertanya-tanya apakah Anda memperhatikan kelas teori komputasi Anda.
Di kelas teori komputasi Anda, Anda belajar tentang mesin keadaan hingga. Mesin negara hingga terdiri dari node dan edge. Setiap tepi diberi anotasi dengan huruf dari alfabet terbatas. Satu atau lebih node adalah node "penerima" khusus dan satu node adalah node "start". Karena setiap huruf dibaca dari kata tertentu, kami melintasi tepi yang diberikan di mesin. Jika kita berakhir dalam keadaan menerima maka kita mengatakan bahwa mesin "menerima" kata itu.
Ekspresi reguler selalu dapat diterjemahkan ke dalam mesin keadaan hingga yang setara. Yaitu, salah satu yang menerima dan menolak kata yang sama dengan ekspresi reguler (di dunia nyata, beberapa bahasa regexp memungkinkan untuk fungsi arbitrer, ini tidak dihitung).
Tidak mungkin untuk membangun mesin negara hingga yang menerima semua palindrome. Pembuktiannya bergantung pada fakta bahwa kita dapat dengan mudah membangun string yang membutuhkan node dalam jumlah besar secara sembarangan, yaitu string
a ^ xba ^ x (mis., aba, aabaa, aaabaaa, aaaabaaaa, ....)
dimana a ^ x adalah x kali berulang. Ini membutuhkan setidaknya x node karena, setelah melihat 'b' kita harus menghitung mundur sebanyak x kali untuk memastikan itu adalah palindrome.
Terakhir, kembali ke pertanyaan awal, Anda dapat memberi tahu pewawancara bahwa Anda dapat menulis ekspresi reguler yang menerima semua palindrom yang lebih kecil dari beberapa panjang tetap yang terbatas. Jika pernah ada aplikasi dunia nyata yang memerlukan identifikasi palindrom maka hampir pasti tidak akan menyertakan palindrom yang panjang secara sembarangan, jadi jawaban ini akan menunjukkan bahwa Anda dapat membedakan kemustahilan teoretis dari aplikasi dunia nyata. Namun, regexp sebenarnya akan cukup panjang, lebih panjang dari program 4 baris yang setara (latihan mudah bagi pembaca: tulis program yang mengidentifikasi palindrom).
sumber
>=1.9
) di siniMeskipun mesin PCRE mendukung ekspresi reguler rekursif (lihat jawaban oleh Peter Krauss ), Anda tidak dapat menggunakan regex di ICU mesin (seperti yang digunakan, misalnya, oleh Apple) untuk mencapai ini tanpa kode tambahan. Anda perlu melakukan sesuatu seperti ini:
Ini mendeteksi palindrome apa pun, tetapi memerlukan loop (yang akan diperlukan karena ekspresi reguler tidak dapat dihitung).
sumber
Itu tidak mungkin. Palindrom tidak didefinisikan oleh bahasa biasa. (Lihat, saya TELAH belajar sesuatu dalam teori komputasi)
sumber
Dengan Perl regex:
Meskipun, seperti yang ditunjukkan banyak orang, ini tidak dapat dianggap sebagai ekspresi reguler jika Anda ingin bersikap tegas. Ekspresi reguler tidak mendukung rekursi.
sumber
/u
pengubah ), atau karena karakter kombinator. (ganti.
dengan\X
escape sequence ).abababa
. Tidak mungkin membuatnya bekerja dengan rekursi untuk setiap input saat menggunakan mesin regex berbasis PCRE. Casimirs regex menggunakan pendekatan yang berbeda, menggunakan iterasi dan status bisa berubah, dan cukup menarik.Ini satu untuk mendeteksi palindrom 4 huruf (misalnya: akta), untuk semua jenis karakter:
Ini satu untuk mendeteksi palindrom 5 huruf (misalnya: radar), hanya memeriksa huruf:
Jadi sepertinya kita membutuhkan regex yang berbeda untuk setiap panjang kata yang memungkinkan. Posting ini di milis Python menyertakan beberapa detail mengapa (Finite State Automata dan pumping lemma).
sumber
Bergantung pada seberapa yakin Anda, saya akan memberikan jawaban ini:
sumber
Ya , Anda dapat melakukannya di .Net!
Kamu bisa cek di sini ! Ini pos yang luar biasa!
sumber
StackOverflow penuh dengan jawaban seperti "Ekspresi reguler? Tidak, mereka tidak mendukungnya. Mereka tidak bisa mendukungnya.".
Yang benar adalah bahwa ekspresi reguler tidak ada hubungannya dengan tata bahasa reguler lagi.Ekspresi reguler modern menampilkan fungsi seperti rekursi dan grup penyeimbang, dan ketersediaan implementasinya terus bertambah (lihat contoh Ruby di sini, misalnya). Menurut pendapat saya, berpegang pada keyakinan lama bahwa ekspresi reguler di bidang kita sama sekali bukan konsep pemrograman hanyalah kontraproduktif. Alih-alih membenci mereka karena pilihan kata yang tidak lagi sesuai, sekarang saatnya kita menerima sesuatu dan melanjutkan hidup.
Berikut kutipan dari Larry Wall , pencipta Perl itu sendiri:
Dan inilah posting blog oleh salah satu pengembang inti PHP :
Karena itu, Anda dapat mencocokkan palindrome dengan ekspresi reguler menggunakan ini:
... yang jelas tidak ada hubungannya dengan tata bahasa biasa.
Info lebih lanjut di sini: http://www.regular-expressions.info/balancing.html
sumber
Seperti yang telah dikatakan beberapa orang, tidak ada satu ekspresi reguler yang akan mendeteksi palindrom umum di luar kotak, tetapi jika Anda ingin mendeteksi palindrom hingga panjang tertentu, Anda dapat menggunakan sesuatu seperti
sumber
Itu bisa dilakukan di Perl sekarang. Menggunakan referensi rekursif:
dimodifikasi berdasarkan bagian terakhir http://perldoc.perl.org/perlretut.html
sumber
Di ruby Anda dapat menggunakan grup penangkapan bernama. jadi sesuatu seperti ini akan berhasil -
coba, berhasil ...
sumber
Sebenarnya lebih mudah melakukannya dengan manipulasi string daripada ekspresi reguler:
Saya menyadari ini tidak benar-benar menjawab pertanyaan wawancara, tetapi Anda dapat menggunakannya untuk menunjukkan bagaimana Anda mengetahui cara yang lebih baik dalam melakukan tugas, dan Anda bukan tipe "orang dengan palu, yang melihat setiap masalah sebagai paku. . "
sumber
Inilah jawaban saya untuk level 5 Regex Golf (Seorang pria, rencana). Ia bekerja hingga 7 karakter dengan Regexp browser (Saya menggunakan Chrome 36.0.1985.143).
Ini satu untuk maksimal 9 karakter
Untuk meningkatkan jumlah maksimal karakter yang berfungsi, Anda akan berulang kali mengganti .? dengan (?: (.).? \ n?)? .
sumber
Ekspresi Reguler Rekursif dapat melakukannya!
Algoritme yang sangat sederhana dan terbukti dengan sendirinya untuk mendeteksi string yang berisi palindrome:
Di rexegg.com/regex-recursion , tutorial menjelaskan cara kerjanya.
Ini berfungsi dengan baik dengan bahasa apa pun, berikut contoh yang diadaptasi dari sumber yang sama (tautan) sebagai bukti-konsep, menggunakan PHP:
keluaran
Perbandingan
Ekspresi reguler
^((\w)(?:(?1)|\w?)\2)$
melakukan pekerjaan yang sama, tetapi sebagai yes / not, bukan "berisi".PS: menggunakan definisi di mana "o" bukan palimbrome, format "dapat-elba" dengan tanda hubung bukan palindrome, tetapi "ableelba "adalah. Menamainya definisi1 .
Ketika "o" dan "mampu-elba" adalah palindrones, definisi penamaan2 .
Membandingkan dengan "palindrome regexes" lainnya,
^((.)(?:(?1)|.?)\2)$
basis-regex di atas tanpa\w
batasan, menerima "mampu-elba".^((.)(?1)?\2|.)$
( @LilDevil ) Gunakan definisi2 (menerima "o" dan "mampu-elba" sehingga membedakan juga dalam pengenalan string "aaaaa" dan "bbbb").^((.)(?1)\2|.?)$
( @Markus ) tidak terdeteksi "kook" dan "bbbb"^((.)(?1)*\2|.?)$
( @Csaba ) Gunakan definisi2 .CATATAN: untuk membandingkan Anda dapat menambahkan lebih banyak kata di
$subjects
dan satu baris untuk setiap ekspresi reguler yang dibandingkan,sumber
Anda juga dapat melakukannya tanpa menggunakan rekursi:
untuk mengizinkan satu karakter:
Bekerja dengan Perl, PCRE
demo
Untuk Java:
demo
sumber
Mengenai ekspresi PCRE (dari MizardX):
/^((.)(?1)\2i>.?)$/
Sudahkah Anda mengujinya? Pada PHP 5.3 saya di bawah Win XP Pro gagal pada: aaaba Sebenarnya, saya mengubah ekspresi ekspresi sedikit, untuk membaca:
/^((.)(?1)*\2i>.?)$/
Saya pikir apa yang terjadi adalah bahwa sementara pasangan luar dari karakter berlabuh, yang dalam tidak. Ini bukanlah jawaban yang lengkap karena meskipun salah menyampaikan pada "aaaba" dan "aabaacaa", namun gagal dengan benar pada "aabaaca".
Saya bertanya-tanya apakah ada perbaikan untuk ini, dan juga, Apakah contoh Perl (oleh JF Sebastian / Zsolt) lulus tes saya dengan benar?
Csaba Gabor dari Wina
sumber
ini berlaku untuk mesin Oniguruma (yang digunakan di Ruby)
diambil dari Rak Buku Pragmatis
sumber
Di Perl (lihat juga jawaban Zsolt Botykai ):
sumber
Seperti yang ditunjukkan oleh ZCHudson , menentukan apakah sesuatu adalah palindrome tidak dapat dilakukan dengan regexp biasa, karena himpunan palindrome bukanlah bahasa biasa.
Saya sama sekali tidak setuju dengan Airsource Ltd ketika dia mengatakan bahwa "itu tidak mungkin" bukanlah jenis jawaban yang dicari pewawancara. Selama wawancara, saya sampai pada pertanyaan seperti ini ketika saya menghadapi kandidat yang baik, untuk memeriksa apakah dia dapat menemukan argumen yang tepat ketika kami melamarnya untuk melakukan sesuatu yang salah. Saya tidak ingin mempekerjakan seseorang yang akan mencoba melakukan sesuatu dengan cara yang salah jika dia lebih tahu.
sumber
sesuatu yang dapat Anda lakukan dengan perl: http://www.perlmonks.org/?node_id=577368
sumber
Saya akan menjelaskan kepada pewawancara bahwa bahasa yang terdiri dari palindrome bukanlah bahasa biasa tetapi bebas konteks.
Ekspresi reguler yang akan cocok dengan semua palindrome adalah tak terbatas . Sebaliknya saya akan menyarankan dia membatasi dirinya baik pada ukuran maksimum palindrome untuk diterima; atau jika semua palindrom diperlukan, gunakan minimal beberapa jenis NDPA, atau cukup gunakan teknik pembalikan / sama dengan string sederhana.
sumber
Hal terbaik yang dapat Anda lakukan dengan regex, sebelum Anda kehabisan grup tangkapan:
Ini akan cocok dengan semua palindrome dengan panjang hingga 19 karakter.
Pemecahan programat untuk semua panjang itu sepele:
sumber
Saya belum memiliki perwakilan untuk mengomentari sebaris, tetapi ekspresi reguler yang disediakan oleh MizardX, dan dimodifikasi oleh Csaba, dapat dimodifikasi lebih lanjut agar berfungsi di PCRE. Satu-satunya kegagalan yang saya temukan adalah string karakter tunggal, tetapi saya dapat mengujinya secara terpisah.
/^((.)(?1)?\2|.)$/
Jika Anda bisa membuatnya gagal di string lain, silakan beri komentar.
sumber
sumber
Dari teori automata, mustahil untuk menyamai paliandrome dengan panjang apa pun (karena itu membutuhkan jumlah memori yang tak terbatas). Tapi MUNGKIN mencocokkan Paliandromes of Fixed Length. Katakanlah mungkin untuk menulis regex yang cocok dengan semua paliandrom dengan panjang <= 5 atau <= 6 dll, tetapi tidak> = 5 dll di mana batas atasnya tidak jelas
sumber
Di Ruby Anda bisa menggunakan
\b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\b
untuk mencocokkan kata-kata palindrome sepertia, dad, radar, racecar, and redivider
. ps: regex ini hanya cocok dengan kata palindrome dengan jumlah huruf ganjil.Mari kita lihat bagaimana ekspresi reguler ini cocok dengan radar. Batas kata \ b cocok di awal string. Mesin regex memasukkan "kata" grup penangkap. [az] cocok dengan r yang kemudian disimpan dalam tumpukan untuk "huruf" grup penangkap pada tingkat rekursi nol. Sekarang mesin regex memasuki rekursi pertama dari grup "kata". (? 'letter' [az]) cocok dan menangkap pada tingkat rekursi satu. Regex memasuki rekursi kedua dari grup "kata". (? 'letter' [az]) menangkap d pada tingkat rekursi dua. Selama dua rekursi berikutnya, grup menangkap a dan r di level tiga dan empat. Rekursi kelima gagal karena tidak ada karakter tersisa di string untuk [az] agar cocok. Mesin regex harus mundur.
Mesin regex sekarang harus mencoba alternatif kedua di dalam grup "kata". [Az] kedua di ekspresi reguler cocok dengan r terakhir dalam string. Mesin sekarang keluar dari rekursi yang berhasil, naik satu tingkat kembali ke rekursi ketiga.
Setelah mencocokkan (& kata) mesin mencapai \ k'letter + 0 '. Referensi belakang gagal karena mesin regex telah mencapai akhir string subjek. Jadi itu mundur sekali lagi. Alternatif kedua sekarang cocok dengan a. Mesin regex keluar dari rekursi ketiga.
Mesin regex telah mencocokkan lagi (& kata) dan perlu mencoba referensi kembali lagi. Referensi latar menentukan +0 atau tingkat rekursi saat ini, yaitu 2. Pada tingkat ini, kelompok penangkap cocok d. Referensi belakang gagal karena karakter berikutnya dalam string adalah r. Mundur lagi, alternatif pertandingan kedua d.
Sekarang, \ k'letter + 0 'cocok dengan huruf a kedua dalam string. Itu karena mesin regex telah tiba kembali pada rekursi pertama di mana grup penangkap cocok dengan yang pertama a. Mesin regex keluar dari rekursi pertama.
Mesin regex sekarang kembali keluar dari semua rekursi. Bahwa tingkat ini, kelompok penangkap disimpan r. Referensi belakang sekarang bisa cocok dengan r terakhir dalam string. Karena mesin tidak lagi berada di dalam rekursi apa pun, mesin melanjutkan dengan sisa regex setelah grup. \ b cocok di akhir string. Akhir regex tercapai dan radar dikembalikan sebagai pertandingan keseluruhan.
sumber
berikut adalah kode PL / SQL yang memberi tahu apakah string yang diberikan adalah palindrome atau tidak menggunakan ekspresi reguler:
sumber
sumber
Regex ini akan mendeteksi palindrom hingga 22 karakter yang mengabaikan spasi, tab, koma, dan tanda kutip.
Mainkan di sini: https://regexr.com/4tmui
sumber
Sedikit penyempurnaan metode Airsource Ltd, dalam kodesemu:
sumber