Для цієї задачі ми говоримо, що шаблон регулярного вираження відповідає рядку, якщо весь рядок узгоджується з шаблоном, а не лише підрядком.
Дано два регулярних виразів моделі і B , ми говоримо , що є більш спеціалізовані , ніж B , якщо кожен рядок, підібраний А також відповідає за B , але не навпаки. Ми говоримо , що є еквівалентом для B , якщо обидві моделі відповідають точно такий же набір рядків. Якщо жодна закономірність не є більш спеціалізованою, ніж інша, або не є рівнозначною, ми говоримо, що A і B є незрівнянними .
Наприклад, модель Hello, .*!
є більш спеціалізованою, ніж .*, .*!
; закономірності (Hello|Goodbye), World!
та Hello, World!|Goodbye, World!
рівнозначні; і закономірності Hello, .*!
і .*, World!
незрівнянні.
Співвідношення "більш спеціалізоване, ніж" визначає суворий частковий порядок набір шаблонів регулярних виразів. Зокрема, для всіх шаблонів A і B справедливо одне з наступних:
- A більш спеціалізований, ніж B ( A < B ).
- B більш спеціалізований, ніж A ( A > B ).
- A і B еквівалентні ( A = B ).
- A і B незрівнянні ( A ∥ B ).
Коли A і B є непорівнянними, ми можемо додатково розрізняти два випадки:
- A і B - неперервні ( A ∥ B ), це означає, що обидві строки не узгоджуються.
- І B є пересічні ( A ≬ B ), що означає , що деякі рядки збігаються з обома.
Виклик
Напишіть програму або функцію, яка бере пару зразків регулярних виразів і порівнює їх, використовуючи вищезазначений порядок. Тобто, якщо два візерунки і В , програма повинна визначити , є чи A < B , A > B , A = B або A ∥ B .
× 92% бонус Додатковий бонус надається, якщо програма, коли шаблони є непорівнянними, програма визначає, перетинаються вони чи не перетинаються.
Вхід і вихід
Програма повинна прийняти два шаблони регулярного вираження, як рядки, в ароматі, визначеному нижче. Ви можете читати вхід через команду STDIN , командний рядок , як аргументи функції або еквівалентний метод . Ви можете припустити, що шаблони дійсні.
Програма повинна створити один із чотирьох рівномірних результатів (або п’ять різних результатів, якщо ви збираєтесь отримати вищевказаний бонус), залежно від результату порівняння (точні результати залежить від вас.) Ви можете записати вихід у STDOUT , поверніть його як результат функції або використовуйте еквівалентний метод .
Regex Flavour
Ви можете підтримувати всі функції, які вам подобаються, але ви повинні підтримувати наступні:
- Чергування з
|
. - Кількісне визначення з
*
. - Групування з
(
і)
. - Узгодження будь-якого символу (можливо, виключаючи нові рядки) із
.
. - (Необов’язково: × 80% бонус) Збірка простих та заперечених класів символів відповідно
[…]
та[^…]
відповідно. Вам не потрібно підтримувати будь-які заздалегідь задані класи символів (наприклад[:digit:]
), але ви повинні підтримувати діапазони символів. - Персонаж рятується с
\
. Потрібно, принаймні, мати можливість схибити спеціальних символів (тобто|*().[^-]\
), а також бажано також використовувати звичайних спеціальних символів в інших ароматах (наприклад{}
), але поведінка під час втечі неспеціальних символів не визначена. Зокрема, вам не доведеться підтримувати спеціальні послідовності евакуації, такі як\n
для нового рядка тощо. Можлива реалізація полягає в тому, щоб просто прийняти символ, що слідує за\
буквальним, буквально.
Ви можете припустити існування вхідного символу, який не може бути узгоджений жодним літералом (тобто він може відповідати лише .
класам символів і заперечувати їх.)
Додаткові правила
- Ви можете використовувати бібліотеки regex або вбудовану функцію регулярного вибору лише для відповідності рядків і їх заміни.
- Ви можете ігнорувати будь-які проблеми, пов’язані з місцевою локацією, наприклад правила зіставлення.
- Затверджуючи очевидне: ваша програма повинна припинитись. Він повинен виконуватись за розумну кількість часу за заданими типовими зразками (безумовно, не більше години, бажано набагато менше.)
Оцінка балів
Це код-гольф. Ваша оцінка є продуктом з розміру коду , в байтах, і будь-який з бонусів . Виграє найнижчий бал .
Випробування
Формат тестів такий:
<Test ID>
<Pattern A>
<Ordering>
<Pattern B>
<Test ID>
<Pattern A>
<Ordering>
<Pattern B>
...
Де <Test ID>
є ідентифікатором для тестового випадку, <Pattern A>
і <Pattern B>
є зразки регулярного вираження та <Ordering>
впорядкування між ними, і є одним із:
<
:<Pattern A>
є більш спеціалізованим, ніж<Pattern B>
.>
:<Pattern B>
є більш спеціалізованим, ніж<Pattern A>
.=
: Шаблони рівноцінні.|
: Шаблони незрівнянні та непересічні.X
: Шаблони незрівнянні та перетинаються.
Особливе значення <empty pattern>
означає порожній візерунок.
А. Основні закономірності
В. Складні візерунки
C. Основні зразки з класами символів
D. Складні візерунки з класами символів
Тестова програма
Наступний фрагмент може бути використаний для порівняння зразків регулярних виразів:
<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>