Для этой задачи мы говорим, что шаблон регулярного выражения соответствует строке, если вся строка соответствует шаблону, а не только подстроке.
Даны два регулярных выражений модели и B , мы говорим , что является более специализированы , чем B , если каждая строка, подобран А также соответствует по B , но не наоборот. Мы говорим , что является эквивалентом для B , если обе модели соответствуют точно такой же набор строк. Если ни одна картина более специализирована , чем другие и они не эквивалентны, мы говорим , что и 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 ), что означает, что ни одна из них не соответствует ни одной строке.
- И B являются пересекающиеся ( A ≬ B ), что означает , что некоторые строки совпадают с обоими.
Вызов
Напишите программу или функцию, которая берет пару шаблонов регулярных выражений и сравнивает их, используя приведенный выше порядок. То есть, если два узоры и В , программа должна определить , является ли A < B , A > B , A = B или A ∥ B .
× 92% Бонус Дополнительный бонус дается, если, когда шаблоны несопоставимы, программа определяет, пересекаются они или не пересекаются.
Вход и выход
Программа должна принимать два шаблона регулярных выражений в виде строк в варианте, определенном ниже. Вы можете прочитать ввод через STDIN , командную строку , как аргументы функции или эквивалентный метод . Вы можете предположить, что шаблоны действительны.
Программа должна произвести один из четырех отдельных выходов (или пять отдельных выходов, если вы хотите получить вышеуказанный бонус), в зависимости от результата сравнения (точные результаты зависят от вас.) Вы можете записать вывод в STDOUT. , вернуть его как результат функции или использовать эквивалентный метод .
Regex Flavor
Вы можете поддерживать любые функции регулярных выражений, которые вам нравятся, но вы должны поддерживать следующие:
- Чередование с
|
. - Количественная оценка с
*
. - Группировка с
(
и)
. - Соответствие любому символу (возможно, исключая переводы строки) с
.
. - (Необязательно: Бонус × 80%) Сопоставление простых и отрицательных классов символов с
[…]
и[^…]
, соответственно. Вам не нужно поддерживать какие-либо предопределенные классы символов (например[:digit:]
), но вы должны поддерживать диапазоны символов. - Персонаж убегает с
\
. По крайней мере, должно быть возможно исключить специальные символы (то есть|*().[^-]\
) и предпочтительно также общие специальные символы в других вариантах (например{}
), но поведение при экранировании не специальных символов не определено. В частности, вам не нужно поддерживать специальные escape-последовательности, такие как\n
перевод строки и тому подобное. Возможная реализация - просто взять символ, следующий за\
литералом.
Вы можете предположить существование входного символа, который не может быть сопоставлен никаким литералом (т. Е. Ему могут соответствовать только .
классы символов с отрицанием.)
Дополнительные правила
- Вы можете использовать библиотеки регулярных выражений или встроенные функции регулярных выражений только с целью сопоставления и замены строк.
- Вы можете игнорировать любые проблемы, связанные с локалью, такие как правила сортировки.
- Чтобы заявить очевидное: ваша программа должна завершиться. Он должен выполняться за разумное количество времени с учетом типовых паттернов (определенно, не более часа, предпочтительно намного меньше).
счет
Это код-гольф. Ваша оценка является продуктом из размера кода , в байтах, и любой из бонусов . Самый низкий балл побеждает.
Тестовые случаи
Формат контрольных примеров следующий:
<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>