出于这个挑战的目的,我们说如果整个字符串(而不只是子字符串)都与该模式匹配,字符串匹配。
给定两个正则表达式模式 一 和 乙,我们说 一个 是更专业比 乙 ,如果每一个被匹配的字符串 一个 也是由匹配 乙 左右,但没有别的办法。我们说, 一个 是等同于 乙 如果两个模式匹配完全相同的一组字符串。如果两个模式都不比另一个更专业,或者它们都不等效,那么我们就说 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 无可比拟时,我们可以进一步区分两种情况:
- 甲 和 乙 是不相交的(甲 ∥ 乙),这意味着没有字符串由两者相匹配。
- 甲 和 乙 的相交(甲 ≬ 乙),这意味着有些字符串由两个相匹配。
挑战
编写一个使用一对正则表达式模式的程序或函数,并按上述顺序对其进行比较。也就是说,如果两个图案是 甲 和 乙,程序应该确定是否 甲 < 乙, 甲 > 乙,
甲 = 乙 或 甲 ∥ 乙。
×92%奖金 如果图案无法比拟时,程序确定它们是相交还是相交,则将提供额外的奖金。
输入输出
该程序应接受以下两种定义的形式的两个正则表达式模式作为字符串。你可以读取通过输入STDIN,所述命令行,作为函数参数或等效的方法。您可以假设这些模式是有效的。
程序应根据比较结果(确切的输出由您决定)产生正好四个不同的输出之一(或者,如果您要获得上述奖金,则可以产生五个不同的输出)之一。您可以将输出写入STDOUT,将其作为函数的结果返回或使用等效的方法。
正则香料
您可以支持所需的任何正则表达式功能,但必须支持以下功能:
- 与交替
|
。 - 定量用
*
。 - 与
(
和分组)
。 - 匹配任何字符(可能不包括换行符)
.
。 - (可选:×80%奖金)分别使用和 匹配简单字符类和否定字符类。您不必支持任何预定义的字符类(例如),但应支持字符范围。
[…]
[^…]
[:digit:]
- 字符转义为
\
。至少应该保留特殊字符(即|*().[^-]\
),最好也保留其他风味的常见特殊字符(例如{}
),但是转义非特殊字符时的行为是不确定的。特别是,您不必支持特殊的转义序列,例如\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>
代表空模式。
A.基本模式
B.复杂模式
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>