Đảo ngược một regex


27

Các thách thức

Cho một regex hợp lệ, xuất ra một regex khớp với cùng một chuỗi các chuỗi, nhưng bị đảo ngược.

Nhiệm vụ

Thách thức này sử dụng hầu hết các hoạt động regex cơ bản: ^, $, ?, +, *, [], {}, |. Không có thứ gọi là nhóm bắt giữ hay bất kỳ thứ phức tạp nào. Nhân vật đặc biệt có thể được trốn thoát.

Đầu vào / đầu ra mẫu

Lưu ý: Đầu vào không hợp lệ sẽ không bao giờ được đưa ra và thường có nhiều câu trả lời có thể có cho một đầu vào nhất định!

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>

Bản giới thiệu

Bản demo làm việc thể hiện đầu vào / đầu ra chính xác. Điều này có một số logic bổ sung để xác nhận các đầu vào không cần thiết trong một câu trả lời thực sự. Xem xét đầu vào không hợp lệ là hành vi không xác định.

Cụ thể

Để đơn giản, tất cả các ký tự đặc biệt hoặc có ý nghĩa đặc biệt của chúng hoặc được thoát; đó là, [[]không phải là một phạm vi nhân vật cho [. Phạm vi chiều dài đến từ ERE POSIX tiêu chuẩn; có nghĩa là, {n}, {n,}, và {n,m}được hỗ trợ. Phạm vi nhân vật [][^]được hỗ trợ. Do các quy tắc này và vì không có đầu vào không hợp lệ nào được đưa ra, bạn thực sự chỉ cần sao chép trực tiếp nội dung của các quy tắc này vào đầu ra. Cuối cùng, sự tham lam không thành vấn đề, tức là không thành vấn đề nếu regex đảo ngược tìm thấy một kết hợp khác trước, nó chỉ cần tìm một kết quả khớp cho cùng một chuỗi.

Chấm điểm

Chương trình nhỏ nhất tính bằng byte (chặn gian lận như yêu cầu mạng) sẽ thắng. Chương trình có thể sử dụng IO thực hoặc chỉ đơn giản là xác định hàm.


1
Bởi vì không có gì ?để đính kèm. Hãy thử gõ /a(?bc)/vào bảng điều khiển của trình duyệt.
TND

3
Có vẻ tốt bây giờ. Bạn có thể muốn thêm một cái gì đó như (^a|b)(c$|d)là một trường hợp thử nghiệm mặc dù.
Martin Ender

Chúng ta có thể cho rằng đầu vào sẽ chỉ chứa các ký tự ASCII có thể in được không? Cụ thể, không có ký tự linefeed?
Martin Ender

1
Chúng ta có nên xem xét vòng loại áp dụng cho các nhóm tức là (a)?(b)+(b)+(a)??
kennytm

1
Danh sách hoạt động regex của bạn bị thiếu (), được sử dụng trong ví dụ của bạn.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Câu trả lời:


7

Võng mạc , 136 114 110 byte

Yo dawg, tôi nghe nói bạn thích regex ...

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

Trường hợp <empty>đại diện cho một dòng dấu trống. Chạy mã từ một tệp duy nhất với -scờ.

... Khi bạn muốn đảo ngược regex, bạn nên sử dụng regex. Khi bạn muốn sử dụng regex, bạn nên sử dụng ngôn ngữ lập trình dựa trên regex.

Mã này giả định rằng đầu vào không chứa ;hoặc !không có khoảng trắng. Mặc dù tôi đồng ý rằng đó là một giả định khá mạnh mẽ và có khả năng không hợp lệ, bạn có thể thay thế ba mã đó bằng ba ký tự không thể in được (như byte rỗng, ký tự chuông, <DEL>bạn đặt tên cho nó) và nó sẽ không ảnh hưởng đến kích thước hoặc chức năng mã ở tất cả.

Tôi sẽ thêm một lời giải thích khi tôi chơi golf.


3
"Tôi bầy * bạn nói
dối

Tôi nghĩ rằng mã cũng giả định rằng regex không chứa bất kỳ ký tự dòng mới nào.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Ồ, đó là sự thật, tôi đã giả định rằng sẽ không có ký tự không thể in được trong đầu vào. Tôi sẽ khắc phục điều đó một khi chúng tôi nhận được làm rõ từ OP. (Nếu bất kỳ ký tự có thể xuất hiện, vẫn còn một số sự kết hợp đó sẽ không xuất hiện trong những thách thức này xem xét một regex hợp lệ, ví dụ ]]], vì vậy một trong hai cách, câu trả lời này sẽ không cần phải sửa đổi nhiều.)
Martin Ender

chơi golf sau hơn một năm? : P
Okx

2

JavaScript ES6, 574 byte

Tôi có thể có thể loại bỏ một vài vartuyên bố.

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, chưa được kiểm tra, 559 byte

Sẽ kiểm tra tại nhà.

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, không mã hóa, 961 byte

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
lol, bạn đã sử dụng regex để đảo ngược regex: D
Kritixi Lithos 4/11/2015

3
@ ΚριτικσιΛίθος Vâng, tôi đã làm: D tôi muốn sử dụng nó để phân tích cú pháp HTML nếu tôi có thể ...
Conor O'Brien

4
"nếu bạn có thể"
Trình tối ưu hóa

1
@ CᴏɴᴏʀO'Bʀɪᴇɴ tôi đã phân tích mã html bằng regex nhưng gặp sự cố nghiêm trọng với ký tự unicode
Abr001am

2
@ CᴏɴᴏʀO'Bʀɪᴇɴ Đây là một thay thế: `code.replace (/.*/," trollolol ");
Kritixi Lithos 04/11/2015

2

JavaScript ES6, 343 byte

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]

Mã gốc (các chức năng, nhưng không có 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]

Mã được triển khai như một trình phân tích cú pháp từ trên xuống đệ quy, do đó, nó có thể gây ra lỗi tràn ngăn xếp trên đầu vào được lồng sâu.

Mã có thể gây ra vòng lặp vô hạn trong các trường hợp không hợp lệ, vì tôi không kiểm tra chúng, lợi dụng mệnh đề "hành vi không xác định".


0

Python 3, 144 byte

(Cái này không hỗ trợ vòng loại trên một nhóm như (a)+(b)*(cde)?.)

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

Các trường hợp thử nghiệm:

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))

Kết quả:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.