Зворотний вираз


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
Чи слід вважати класифікаторами, застосованими для груп, тобто (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прапором.

... коли ви хочете повернути регекс, ви повинні використовувати регулярний вираз. Коли ви хочете використовувати regex, ви повинні використовувати мову програмування на основі регулярних виразів.

Цей код передбачає, що вхід не містить ;ні !ані пробілів. Хоча я погоджуюся, що це досить сильне та потенційно недійсне припущення, ви можете замінити цих трьох у коді будь-якими трьома недрукованими символами (наприклад, нульовими байтами, символом дзвоника, <DEL>ви його називаєте), і це не вплине на розмір коду чи функціональність зовсім.

Я додам пояснення, коли закінчу гольф.


3
"Я стадо * ти смакуєш *"
lirtosiast

Я думаю, що код також передбачає, що регулярний вираз не містить жодного необробленого символу нового рядка.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ О, це правда, я був припущений, що у вводі не буде друкованих символів. Я виправлю це, як тільки ми отримаємо роз’яснення з ОП. (Якщо можуть з’явитися будь-які символи, все ж є певні комбінації, які не відображатимуться в тому, що ця виклик вважає дійсним регулярним виразом, наприклад ]]], так що в будь-якому випадку ця відповідь не потребує великих змін.)
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
хаха, ти використовував регулярний вираз для зворотного
виразного позначення

3
@ ΚριτικσιΛίθος Так, я зробив: D Я б використав його для розбору HTML, якщо зможу ...
Conor O'Brien

4
"якби міг"
оптимізатор

1
@ CᴏɴᴏʀO'Bʀɪᴇɴ я розібрав html-коди з regex, але у мене виник серйозна проблема з символами unicode
Abr001am

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

Пітон 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.