정규식 반전


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

3
지금은 좋아 보인다. (^a|b)(c$|d)테스트 케이스 와 같은 것을 추가하고 싶을 수도 있습니다 .
Martin Ender

입력에 인쇄 가능한 ASCII 문자 만 포함한다고 가정 할 수 있습니까? 특히 줄 바꿈 문자가 없습니까?
Martin Ender

1
예를 (a)?(b)+들어 그룹에 적용되는 한정자를 고려해야 (b)+(a)?합니까?
kennytm

1
귀하 ()의 예제에서 사용되는 정규식 작업 목록이 누락되었습니다 .
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

답변:


7

망막 , 136 (114) 110 바이트

Yo dawg, 나는 당신이 정규 표현식을 좋아한다고 들었습니다 ...

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

어디 <empty>빈 후행 라인을 나타냅니다. -s플래그 를 사용하여 단일 파일에서 코드를 실행하십시오 .

... 정규식을 되돌리려면 정규식을 사용해야합니다. 정규식을 사용하려면 정규식 기반 프로그래밍 언어를 사용해야합니다.

이 코드는 입력에 공백 ;도 포함되지 않는다고 가정 !합니다. 나는 그것이 매우 강력하고 잠재적으로 유효하지 않은 가정이라는 것에 동의하지만 코드 에서이 세 가지를 인쇄 할 수없는 문자 (예 : null 바이트, 벨 문자, <DEL>이름 지정)로 바꿀 수 있으며 코드 크기 또는 기능에 영향을 미치지 않습니다 조금도.

골프를 마치면 설명을 추가하겠습니다.


3
"I herd * you liek *"
lirtosiast

코드는 정규식에 줄 바꿈 문자가 포함되어 있지 않다고 가정합니다.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 아, 사실, 입력에 인쇄 할 수없는 문자가 없을 것이라는 가정하에있었습니다. OP에서 설명을 받으면 수정하겠습니다. (캐릭터가 나타날 수 있더라도이 도전 과제가 유효한 정규 표현식으로 간주되는 부분에 표시되지 않는 특정 조합이 여전히 있습니다. 예를 들어이 ]]]답변에는 많은 수정이 필요하지 않습니다.)
Martin Ender

1 년 넘게 골프를 쳤습니까? : P
Okx

2

자바 스크립트 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``}}

자바 스크립트 ES5, ungolfed, 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 : LOL, 당신은 역 정규식에 대한 정규식 사용
Kritixi LITHOS

3
@ ΚριτικσιΛίθος 그렇습니다, 나는 : D 가능하다면 HTML을 파싱하기 위해 그것을 사용할 것입니다 ...
Conor O'Brien

4
"가능한 경우"
Optimizer

1
@ CᴏɴᴏʀO'Bʀɪᴇɴ 나는 정규식으로 HTML 코드를 파싱했지만 유니 코드 문자와 관련하여 심각한 문제가 발생했습니다
Abr001am

2
@ CᴏɴᴏʀO'Bʀɪᴇɴ 이것은 대안입니다 :`code.replace (/.*/, "trollolol");
Kritixi Lithos

2

자바 스크립트 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

파이썬 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.