正規表現を逆にする


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)ただし、テストケースのようなものを追加することもできます。
マーティンエンダー

入力に印刷可能なASCII文字のみが含まれると想定できますか?特に、改行文字はありませんか?
マーティンエンダー

1
私たちはグループに適用される修飾子は、IE検討すべき(a)?(b)+(b)+(a)?
ケニー

1
正規表現操作のリストがありません()。これは例で使用されています。
-n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

回答:


7

網膜136の 114 110バイト

Yo dawg、正規表現が好きだと聞きました...

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

where <empty>は空の末尾の行を表します。-sフラグを使用して、単一のファイルからコードを実行します。

...正規表現を逆にする場合は、正規表現を使用する必要があります。正規表現を使用する場合は、正規表現ベースのプログラミング言語を使用する必要があります。

このコードは、入力にスペースもスペース;も含まれていない!ことを前提としています。それはかなり強力で潜在的に無効な仮定であることに同意しますが、コード内のこれらの3つを3つの印刷できない文字(ヌルバイト、ベル文字、<DEL>名前など)で置き換えることができ、コードサイズや機能には影響しませんまったく。

ゴルフが終わったら説明を追加します。


3
「私は群れ*あなたliek *」
lirtosiast

このコードでは、正規表現に生の改行文字が含まれていないことも想定しています。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ああ、それは本当です、私は入力に印刷できない文字がないと仮定していました。OPから明確になったら、修正します。(文字が表示される場合、このチャレンジが有効な正規表現とみなすものには表示されない特定の組み合わせがまだあります。たとえば]]]、どちらにしても、この答えはあまり変更する必要はありません。)
Martin Ender

1年以上ゴルフをしましたか?: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、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
Kritixi Lithos

3
@ΚριτικσιΛίθοςはい、私がやった:私はできればD私は...パースHTMLにそれを使用したい
コナー・オブライエン

4
「できれば」
オプティマイザー

1
@CᴏɴᴏʀO'Bʀɪᴇɴ正規表現でhtmlコードを解析しましたが、ユニコード文字で深刻な問題が発生しました
Abr001am

2
@CᴏɴᴏʀO'Bʀɪᴇɴこれは代替案です: `code.replace(/.*/、" trollolol ");
Kritixiリトス

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.