逆转正则表达式


27

挑战

给定有效的正则表达式,输出匹配相同字符串集但反向的正则表达式。

任务

这个挑战使用最基本的正则表达式操作:^$?+*[]{}|。没有捕获组或任何复杂的东西。特殊字符可以转义。

样本输入/输出

注意:永远不会给出无效的输入,对于给定的输入,通常会有多个可能的答案!

Input      | Sample Output
-----------|-------------
abc        | cba
tuv?       | v?ut
a(b|c)     | (c|b)a
1[23]      | [23]1
a([bc]|cd) | (dc|[bc])a
^a[^bc]d$  | ^d[^bc]a$
x[yz]{1,2} | [yz]{1,2}x
p{2}       | p{2}
q{7,}      | q{7,}
\[c[de]    | [de]c\[
ab[c       | <output undefined>
a(?bc)     | <output undefined>
a[]]bc     | <output undefined>

演示版

演示正确输入/输出的工作演示。这有一些额外的逻辑可用于验证输入,而这在实际答案中是不必要的。将无效输入视为未定义行为。

细节

为简单起见,所有特殊字符要么具有特殊含义,要么被转义。也就是说,[[]不是的字符范围[。长度范围来自标准POSIX ERE;也就是{n}{n,}{n,m}支持。字符范围[][^]被支持。由于这些规则,并且由于没有给出无效的输入,因此您实际上只需要将这些内容直接复制到输出中即可。最后,贪婪无关紧要,即,反向正则表达式是否首先找到不同的匹配并不重要,它只需要为同一组字符串找到匹配即可。

计分

以字节为单位的最小程序(除非作弊,例如网络请求)获胜。程序既可以使用实际的IO,也可以简单地定义一个函数。


1
因为没有什么?要附加的。尝试输入/a(?bc)/浏览器的控制台。
TND 2015年

3
现在看起来不错。您可能想要添加类似的内容(^a|b)(c$|d)作为测试用例。
Martin Ender 2015年

我们是否可以假定输入将仅包含可打印的ASCII字符?特别是没有换行符?
马丁·恩德

1
我们应该考虑应用在团体资格赛,即(a)?(b)+(b)+(a)?
kennytm 2015年

1
您的正则表达式操作列表丢失了(),在您的示例中使用了该列表。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 2015年

Answers:


7

视网膜136个 114 110字节

da,我听说您喜欢regex ...

^
;
(T`^$`$^`;.
(.*);(\[(\\.|[^]])*]|\\.|.)([*+?]|{\d+(,|,\d+)?})?
$2$4!$1;
^\(!
) 
^\)(.*)!(.+?) 
($2$1
;$|!
<empty>

其中<empty>代表空的尾随线。从带有-s标志的单个文件运行代码。

...当您想反向使用正则表达式时,应使用正则表达式。当您想使用正则表达式时,应使用基于正则表达式的编程语言。

此代码假定输入既不包含空格;也不包含!空格。尽管我同意这是一个很强的假设并且可能是无效的假设,但是您可以将代码中的这三个替换为任何三个不可打印的字符(例如,空字节,贝尔字符,<DEL>将其命名),并且这不会影响代码的大小或功能完全没有

打完高尔夫球后,我会加一个解释。


3
“我
成群

我认为代码还假定正则表达式不包含任何原始换行符。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 2015年

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳哦,是的,我当时假设输入中将没有不可打印的字符。一旦我们从OP中得到澄清,我将修复该问题。(如果可以出现任何字符,则在此挑战认为有效的正则表达式中仍然存在某些组合,例如]]],所以无论哪种方式,此答案都不需要太多修改。)
Martin Ender

一年后打高尔夫球了吗?:P
Okx

2

JavaScript ES6,574字节

我可能可以删除一些var声明。

R=e=>{for(var s=0,c=[],h=/(\?|\+|\{\d*,*\d*\}|\*)(\?*)/,t=0;t<e.length;t++)switch(s){case 0:switch(e[t]){case"\\":t++,c.push("\\"+e[t]);break;case"[":j=t,s=1;break;case"(":k=t,s=2;break;default:var l=e.search(h,t);(l>=t+1||0>l)&&c.push(l==t+1?e[t]+e.slice(t,e.length).match(h)[0]:e[t])}break;case 1:"\\"==e[t]?t++:"]"==e[t]&&(c.push(e.slice(j,t+1)+(e.search(h,t)==t+1?e.slice(t,e.length).match(h)[0]:"")),s=0);break;case 2:"\\"==e[t]?t++:")"==e[t]&&(a=R(e.slice(k+1,t)),c.push("("+a+")"),s=0)}c.reverse(),r=c;var i=c.length-1;return"^"==c[i]&&(r[i]="$"),"$"==c[0]&&(r[0]="^"),r.join``}}

JS ES6,未经测试,559字节

会在家测试。

R=e=>{for(s=0,c=[],h=/(\?|\+|\{\d*,*\d*\}|\*)(\?*)/,t=0;t<e.length;t++)switch(s){case 0:switch(e[t]){case"\\":t++,c.push`\\${e[t]}`;break;case"[":j=t,s=1;break;case"(":k=t,s=2;break;default:l=e.search(h,t);(l>=t+1||0>l)&&c.push(l==t+1?e[t]+e.slice(t,e.length).match(h)[0]:e[t])}break;case 1:"\\"==e[t]?t++:"]"==e[t]&&(c.push(e.slice(j,t+1)+(e.search(h,t)==t+1?e.slice(t,e.length).match(h)[0]:"")),s=0);break;case 2:"\\"==e[t]?t++:")"==e[t]&&(a=R(e.slice(k+1,t)),c.push`(${a})`,s=0)}c.reverse(),r=c;i=c.length-1;return"^"==c[i]&&(r[i]="$"),"$"==c[0]&&(r[0]="^"),r.join``}}

JavaScript ES5,无高尔夫,961字节

function revRegex(str){
 var mode = 0;
 var oS = [];
 var post = /(\?|\+|\{\d*,*\d*\}|\*)(\?*)/;
 for(var i=0;i<str.length;i++){
  switch(mode){
   case 0: switch(str[i]){
    case "\\": i++; oS.push("\\"+str[i]); break;
    case "[": j=i; mode = 1; break;
    case "(": k=i; mode = 2; break;
    default:
     var pLoc = str.search(post,i);
     if(pLoc>=i+1||pLoc<0){ // current is not pLoc
      if(pLoc==i+1){
       oS.push(str[i] + str.slice(i,str.length).match(post)[0]);
      } else {
       oS.push(str[i]);
      }
     }
   }; break;
   case 1: if(str[i]=="\\") i++; else if(str[i]=="]"){oS.push

(str.slice(j,i+1)+(str.search(post,i)==i+1?str.slice

(i,str.length).match(post)[0]:""));mode = 0}; break;
   case 2: if(str[i]=="\\") i++; else if(str[i]==")")

{a=revRegex(str.slice(k+1,i));oS.push("("+a+")");mode = 

0};break;
  }
 }
 oS.reverse();
 r=oS;
 var l=oS.length-1;
 if(oS[l]=="^") r[l]="$";
 if(oS[0]=="$") r[0]="^";
 return r.join("");
}

5
大声笑,您使用过正则表达式来反转正则表达式:D
Kritixi Lithos 2015年

3
@ΚριτικσιΛίθος是的,我做到了:D如果可以的话,我会用它来解析HTML ...
Conor O'Brien

4
“如果可以的话”
Optimizer

1
@CᴏɴᴏʀO'Bʀɪᴇɴ我用正则表达式解析了html代码,但unicode字符遇到了严重问题
Abr001am 2015年

2
@CᴏɴᴏʀO'Bʀɪᴇɴ这是另一种选择:`code.replace(/.*/,“ trollolol”);
Kritixi Lithos

2

JavaScript ES6,343字节

t=r=>(u="substr",T="(?:[+?*]|{\\d+(?:,\\d*)?})?)([^]*)",(c=r[0])=="(")?([n,s]=v(r[u](1)),[_,q,s]=s.match("^(\\)"+T),["("+n+q,s]):c==")"||c==null?["",r]:c=="^"?["^",r[u](1)]:c=="$"?["^",r[u](1)]:r.match("^("+/(?:\[(?:[^\]\\]|\\[^])*\]|[^[\\]|\\[^])/.source+T).slice(1);(v=r=>{var o="";do{[n,r]=t(r);o=n+o;}while(n&&r);return[o,r]})(prompt())[0]

原始代码(功能,但没有prompt):

function reverse(regex) {
    var out = "";
    do {
        // console.log("calling term");
        var [node, regex] = term(regex);
        // console.log("reverse: " + [node, regex]);
        out = node + out;
    } while (node && regex);
    return [out, regex];
}

function term(regex) {
    switch (regex[0]) {
        case "(":
            // console.log("calling reverse");
            var [node, sequel] = reverse(regex.substr(1));
            // console.log("term: " + regex + " / " + [node, sequel]);
            var [_, quantifier, sequel] = sequel.match(/^(\)(?:[+?*]|{\d+(?:,\d*)?})?)([^]*)/);
            return ["(" + node + quantifier, sequel];
        case ")":
        case void 0:
            return ["", regex];
        case "^":
            return ["$", regex.substr(1)];
        case "$":
            return ["^", regex.substr(1)];
        default:
            return regex.match(/^((?:\[(?:[^\]\\]|\\[^])*\]|[^[\\]|\\[^])(?:[+?*]|{\d+(?:,\d+)?})?)([^]*)/).slice(1);
    }
}

reverse("^\\(([The(){}*\\] ]{2,3}world\\\\(begin(ner|ning)?|ends*)+|Con\\|ti\\*n\\)ue...[^%\\[\\]()\\\\])$")[0]

该代码被实现为递归的自上而下的解析器,因此可能会在深度嵌套的输入上导致堆栈溢出。

该代码在无效的情况下可能会导致无限循环,因为我没有利用“未定义的行为”子句对它们进行测试。


0

Python 3,144个字节

(此人不支持类似的组中的限定词(a)+(b)*(cde)?。)

import re;f=lambda x:''.join({e:e,'^':'$','$':'^','(':')',')':'('}[e]for e in re.findall(r'(?:\\.|\[(?:\\?.)+?\]|.)(?:[?+*]|\{.+?\})?',x)[::-1])

测试用例:

test_cases = [
    # Provided test cases
    r'abc',
    r'tuv?',
    r'a(b|c)',
    r'1[23]',
    r'a([bc]|cd)',
    r'^a[^bc]d$',
    r'x[yz]{1,2}',
    r'p{2}',
    r'q{7,}',
    r'\[c[de]',

    # Pathological cases
    r'a{3}b',
    r'(a)?(b)+',            # <-- currently failing!
    r'[\[]{5}[^\]]{6}',
    r'[\[]\]{7}',
    r'[\[\]]{8,9}',
    r'\(\)\^\$',

    # Undefined cases
    r'ab[c',
    r'a(?bc)',
    r'a[]]bc',
]

for t in test_cases:
    print(t, '->', f(t))

结果:

abc -> cba
tuv? -> v?ut
a(b|c) -> (c|b)a
1[23] -> [23]1
a([bc]|cd) -> (dc|[bc])a
^a[^bc]d$ -> ^d[^bc]a$
x[yz]{1,2} -> [yz]{1,2}x
p{2} -> p{2}
q{7,} -> q{7,}
\[c[de] -> [de]c\[
a{3}b -> ba{3}
(a)?(b)+ -> )+b))?a)                    # <-- note: wrong
[\[]{5}[^\]]{6} -> [^\]]{6}[\[]{5}
[\[]\]{7} -> \]{7}[\[]
[\[\]]{8,9} -> [\[\]]{8,9}
\(\)\^\$ -> \$\^\)\(
ab[c -> c[ba
a(?bc) -> (cb(?a
a[]]bc -> cb[]]a
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.