Untuk tujuan tantangan ini, kami mengatakan bahwa pola regex cocok dengan string jika seluruh string dicocokkan dengan pola, bukan hanya substring.
Mengingat dua pola regex A dan B , kita mengatakan bahwa A adalah lebih khusus dari B jika setiap string yang cocok dengan A juga cocok dengan B tetapi tidak sebaliknya. Kita mengatakan bahwa A adalah setara dengan B jika kedua pola sama persis dengan set yang sama string. Jika pola tidak lebih khusus dari yang lain mereka juga tidak setara, kita mengatakan bahwa A dan B yang tak tertandingi .
Misalnya, polanya Hello, .*!
lebih khusus daripada .*, .*!
; polanya (Hello|Goodbye), World!
dan Hello, World!|Goodbye, World!
setara; dan pola Hello, .*!
dan.*, World!
tidak ada bandingannya.
Relasi "lebih terspesialisasi daripada" mendefinisikan urutan parsial ketat pada set pola regex. Khususnya, untuk semua pola A dan B , tepat satu dari yang berikut ini benar:
- A lebih khusus daripada B ( A < B ).
- B lebih khusus daripada A ( A > B ).
- A dan B adalah setara ( A = B ).
- A dan B tidak tertandingi ( A ∥ B ).
Ketika A dan B tidak dapat dibandingkan, kita dapat membedakan lebih lanjut antara dua kasus:
- A dan B adalah saling lepas ( A ∥ B ), yang berarti bahwa ada string cocok dengan mereka berdua.
- A dan B yang berpotongan ( A ≬ B ), yang berarti bahwa beberapa string dicocokkan oleh keduanya.
Tantangan
Tulis program atau fungsi yang mengambil sepasang pola regex dan membandingkannya menggunakan urutan di atas. Artinya, jika dua pola yang A dan B , program harus menentukan apakah A < B , A > B ,
A = B atau A ∥ B .
× 92% Bonus tambahan diberikan jika, ketika polanya tidak tertandingi, program menentukan apakah mereka berpotongan atau terpisah.
Masukan dan keluaran
Program harus menerima dua pola regex, sebagai string, dalam rasa yang ditentukan di bawah ini. Anda dapat membaca input melalui STDIN , baris perintah , sebagai argumen fungsi atau metode yang setara . Anda dapat mengasumsikan bahwa polanya valid.
Program harus menghasilkan satu dari empat output yang berbeda (atau lima output yang berbeda jika Anda akan mendapatkan bonus di atas,) tergantung pada hasil perbandingan (output yang tepat terserah Anda.) Anda dapat menulis output ke STDOUT , kembalikan sebagai hasil fungsi atau gunakan metode yang setara .
Regex Flavour
Anda dapat mendukung fitur regex apa pun yang Anda suka, tetapi Anda harus mendukung yang berikut:
- Pergantian dengan
|
. - Kuantifikasi dengan
*
. - Pengelompokan dengan
(
dan)
. - Mencocokkan karakter apa pun (mungkin tidak termasuk baris baru) dengan
.
. - (Opsional: × 80% Bonus) Mencocokkan kelas karakter yang sederhana dan yang dinegasikan dengan
[…]
dan[^…]
, masing-masing. Anda tidak harus mendukung kelas karakter yang telah ditentukan sebelumnya (mis.[:digit:]
) Tetapi Anda harus mendukung rentang karakter. - Karakter lolos dengan
\
. Setidaknya harus dimungkinkan untuk meloloskan karakter khusus (yaitu|*().[^-]\
) dan lebih disukai juga karakter khusus yang umum dalam rasa lain (misalnya{}
), tetapi perilaku ketika melarikan diri karakter tidak spesifik tidak ditentukan. Khususnya, Anda tidak harus mendukung urutan pelarian khusus seperti\n
untuk baris baru dan sejenisnya. Sebuah implementasi yang mungkin adalah hanya untuk mengambil karakter mengikuti huruf\
sebagai literal.
Anda dapat mengasumsikan keberadaan karakter input yang tidak dapat dicocokkan dengan literal apa pun (yaitu hanya dapat dicocokkan dengan .
dan kelas karakter yang dinegasikan.)
Aturan tambahan
- Anda dapat menggunakan pustaka regex atau fungsionalitas regex bawaan hanya untuk tujuan pencocokan dan penggantian string.
- Anda dapat mengabaikan masalah terkait lokal, seperti aturan pengumpulan.
- Untuk menyatakan yang sudah jelas: program Anda harus diakhiri. Itu harus dieksekusi dalam jumlah waktu yang wajar diberikan pola-pola khas (pasti tidak lebih dari satu jam, lebih disukai jauh lebih sedikit.)
Mencetak gol
Ini adalah kode-golf. Skor Anda adalah produk dari ukuran kode , dalam byte, dan bonus apa pun . The skor terendah menang.
Uji Kasus
Format kasus uji adalah sebagai berikut:
<Test ID>
<Pattern A>
<Ordering>
<Pattern B>
<Test ID>
<Pattern A>
<Ordering>
<Pattern B>
...
Di mana <Test ID>
pengenal untuk kasus uji, <Pattern A>
dan <Pattern B>
merupakan pola regex dan <Ordering>
urutan di antara mereka, dan merupakan salah satu dari:
<
:<Pattern A>
lebih terspesialisasi daripada<Pattern B>
.>
:<Pattern B>
lebih terspesialisasi daripada<Pattern A>
.=
: Polanya sama.|
: Pola-pola tidak tertandingi dan terpisah.X
: Pola-pola tidak tertandingi dan berpotongan.
Nilai khusus <empty pattern>
berarti pola kosong.
A. Pola dasar
B. Pola kompleks
C. Pola dasar dengan kelas karakter
D. Pola kompleks dengan kelas karakter
Program Tes
Cuplikan berikut dapat digunakan untuk membandingkan pola regex:
<style>#main {display: none;}#main[loaded] {display: inline;}.pattern_container {position: relative;}.pattern_underlay, .pattern {font: 12pt courier, monospace;overflow: hidden;white-space: pre;padding: 7px;box-sizing: border-box;}.pattern_underlay {background-color: #dddddd;color: #707070;border-radius: 4px;box-shadow: 0.5px 0.5px 2.5px #aaaaaa;}.pattern_underlay[error] {background-color: #ffccbb;}.pattern {position: absolute;left: 0px;top: 0px;background: none;border: none;width: 100%;height: 100%;resize: none;white-space: normal;}#ordering {min-width: 28pt;text-align: center;font-size: 16pt;}#status {padding: 5px;background-color: #fffdce;box-shadow: 1.5px 1.5px 3.5px #aaaaaa;font-size: 10pt;white-space: pre;display: none;}#status[error] {display: inline;background-color: #ffe8df;}#status[loading] {display: inline;}.inline_code {background-color: #dddddd;font: 12pt courier, monospace;padding: 2px;}.placeholder {visibility: hidden;}.error_text {background-color: #fffcb7};</style><span id="main"><table><tr><td><div class="pattern_container"><div class="pattern_underlay" id="pattern1_underlay"></div><textarea class="pattern" id="pattern1" oninput="compare()">Hello, .*!</textarea></div></td><td id="ordering"></td><td><div class="pattern_container"><div class="pattern_underlay" id="pattern2_underlay"></div><textarea class="pattern" id="pattern2" oninput="compare()">.*, .*!</textarea></div></td></tr></table><br></span><span id="status" loading>Loading...</span><script type='text/javascript'>var Module = {setStatus: function (status) {document.getElementById("status").innerHTML = status;if (status == "") {compare();document.getElementById("status").removeAttribute("loading");document.getElementById("main").setAttribute("loaded", 1);}}};function underlay_chars(str) {if (/^\n*$/.exec(str))return str.split("\n").map(function () { return '<span class="placeholder"> \n</span>'; });if (str.indexOf("\n") >= 0)str = str.replace(/\s*$/gm, function (m) { return m.replace(/[^\n]/g, "\0"); });return (str + "\n").split("").map(function (c) {if (c == "\0") return "·";else return '<span class="placeholder">' + c + '</span>';});}function underlay_str(str) {return underlay_chars(str).join("");}function str_to_array32(str) {a = [];for (c of str) {n = c.charCodeAt(0);a.push(n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, n >> 24);}a.push(0, 0, 0, 0);return a;}function compare() {try {for (e of ["pattern1_underlay", "pattern2_underlay", "status"])document.getElementById(e).removeAttribute("error");for (e of ["pattern1", "pattern2"])document.getElementById(e + "_underlay").innerHTML = underlay_str(document.getElementById(e).value);c = Module.ccall("regex_compare", "number", ["array", "array"], [str_to_array32(document.getElementById("pattern1").value),str_to_array32(document.getElementById("pattern2").value)]);if (c >= 0)document.getElementById("ordering").innerHTML = "∥≬<>="[c];else {i = Module.ccall("regex_error_index", "number", [], []);l = Module.ccall("regex_error_length", "number", [], []);e = document.getElementById("pattern" + -c + "_underlay");t = underlay_chars(document.getElementById("pattern" + -c).value);e.setAttribute("error", 1);e.innerHTML =t.slice(0, i).join("") +'<span class="error_text">' + t.slice(i, i + l).join("") + "</span>" +t.slice(i + l).join("");e.setAttribute("error", 1);throw "Pattern error: " + Module.ccall("regex_error", "string", [], []).replace(/`(.*?)'/g, '<span class="inline_code">$1</span>');}} catch (e) {document.getElementById("ordering").innerHTML = "??";document.getElementById("status").innerHTML = e;document.getElementById("status").setAttribute("error", 1);}}</script><script async type="text/javascript" src="https://gist.githack.com/anonymous/91f27d6746566c7b4e4c/raw/c563bf84a01c3a1c6e5f021369a3e730a2e74a1a/rpo.js"></script>
Jawaban:
Python 2, 522 byte * .92 = 480,24
537,28Edit 2 : -60 byte
Edit : Menambahkan penjelasan.
Ditetapkan adalah fungsi
f
yang mengambil dua string pola sebagai argumen dan kembali'<'
,'='
,'>'
,'|'
, atau'X'
. Diperlukan kurang dari satu menit untuk memproses semua kasus uji.Kode ini terdiri dari berikut ini, tetapi dengan
\r
,\n
\t
, dan lolos hex (tapi tidak\0
) diganti dengan nilai-nilai byte yang sebenarnya mereka.Pernyataan di atas menyebabkan kode berikut ini dijalankan:
Jika sampel kode kedua disimpan dalam string
s
, sesuatu yang mirip dengan yang pertama dapat dihasilkan oleh ekspresi'#encoding=Latin\nexec"""%s"""'%__import__('zlib').compress(s)
. Mungkin perlu untuk memperbaiki beberapa karakter seperti null bytes atau backslash. Kode unzipped hampir1000800 byte jadi mungkin lebih membingungkan daripada golf ... tapi setidaknya saya berhasil sedikit golf encoding: dariLatin1
keLatin
.Penjelasan
Program ini bekerja dengan menggunakan indeks string sebagai cara kasar untuk melacak status parsing string. The
n
Fungsi membangun tabel transisi. Pertama ia mem-parsing string dan menemukan semua contoh dari dua jenis transisi. Pertama, ada transisi yang tidak melibatkan penambahan surat ke string. Misalnya, melompat dari a*
ke awal ekspresi terkuantifikasi. Kedua, ada transisi menambahkan karakter, yang hanya bergerak maju dengan satu indeks. Kemudian penutupan transitif dari transisi tanpa-karakter dihitung, dan itu diganti untuk tujuan transisi 1-karakter. Jadi ini mengembalikan pemetaan indeks dan karakter ke satu set indeks.Fungsi utama melakukan BFS atas kemungkinan string input. Ini melacak satu set semua indeks yang mungkin untuk fragmen string apa pun yang sedang dipertimbangkan. Yang kami tertarik untuk menemukan adalah keadaan yang diterima oleh kedua regex, atau oleh satu dan bukan yang lain. Untuk menunjukkan bahwa suatu regex diterima, Anda hanya perlu menemukan satu jalur transisi yang mungkin ke akhir pola. Tetapi untuk menunjukkan bahwa seseorang ditolak, perlu untuk menganalisis semua jalur yang mungkin. Oleh karena itu, untuk menentukan apakah himpunan status yang mungkin untuk pola A dan pola B sudah dicakup oleh yang telah dianalisis sebelumnya, pasangan negara tunggal dalam satu regex dan himpunan semua negara yang memungkinkan di yang lain dicatat. Jika tidak ada yang baru, maka boleh kembali. Tentu saja, itu juga akan mungkin, dan lebih sedikit karakter,
sumber
x 0.92
bonus saat Anda menghitung skor Anda. Dan, tentu saja, sebuah penjelasan diterima!Haskell,
560553618mungkin mendapatkan beberapa bonus dilakukan di masa depan.
ini belum sepenuhnya golf.
penjelasan algoritma yang bergelombang:
reg!reg'
mengembalikan karakter yang diperlukan, salah satu dari "= <> x".a#b
benar jika tidak setiap string yanga
cocok juga cocok denganb
.c%reg
adalah daftar ekspresi reguler yangreg
cocok denganc:s
salah satu regexps dalam output yang cocoks
. saya pada dasarnya sebagian cocok dengan regex. kecuali jikac
adalah'\0'
. maka itu memaksareg
untuk tidak mendapatkan input lagi, kembali[]
jikareg
harus mendapatkan lebih banyak input untuk mencocokkan dan[""]
sebaliknya.#
bekerja dengan menghasilkan daftar yang terbatas dari semua "regex-state" yang mungkin, kedua regexps akan berada di setelah string arbitrer. kemudian untuk memeriksa apakaha<b
kita memeriksa cuaca ada "regex-state" di manaa
sepenuhnya cocok tetapib
tidak sepenuhnya cocok.sumber
B4
.