Стрічка каналу режексперсом


11

Ваше завдання - створити програму, яка визначає, чи задана рядок є дійсним регулярним виразом чи не використовує фрагменти коду, що походять з сайтів мережі StackExchange.

Для цілей цього завдання, регулярний вираз говір буде урізана і в основному мінімальний набір мета-символів: ()*?|\. Таким чином, ви не зможете використовувати вбудовані парсекс-аналізатори.

  • \використовується для втечі мета-символів. За ним повинен дотримуватися мета-символ.
  • Нескорочені дужки повинні бути збалансованими
  • *і ?йому передує або немета-символ, або кругла група, або мета-символ, що уникнув.
  • Усі інші символи ASCII для друку, а також нова лінія, вкладка та пробіл повинні підтримуватися як неметалічні символи. Що відбувається з рядком, що містить інші символи, не визначено.
  • Справжнє значення регулярного вираження не важливе для цього завдання.

Приклади

Truthy:
  abc
  a?
  (a|)*
  ()
  a|b*
  \*
  \\
  \\*
  a*b?(cd|e)
  +
  [
  }
  (123\))*
  \|
  (a(b(c|d)*e)*f)*
  (|\)*)
  (abc)+*
  (abc)+
  +abc

^ last test case is an actual newline

Falsy:
  ?abc
  *
  **
  \
  (
  a*?
  a?*
  ?
  a)
  (\)
  (|\)*
  \()
  |*
  (?:abc)
  \\**
  \n

Оцінка балів

Ваш загальний бал - це кількість фрагментів, взятих із запитань та відповідей навколо StackExchange.

  • Повторні фрагменти рахуються стільки ж разів, скільки вони використовуються.
  • Простір можна додавати та видаляти вільно (через Python, Haskell та інших мов, чутливих до пробілів) і не зараховується до вашої кількості фрагментів.
    • Виняток буде, якщо ваш код фактично написаний на Whitespace .
  • Фрагменти дозволено з будь-якого сайту StackExchange, якщо вони походять із питань, відповідей та коментарів, які старіші (включаючи час редагування - використовуйте старі версії, якщо потрібно), ніж це завдання. (24 вересня 2019 р., 15:30 UTC)
  • Фрагменти можуть надходити з будь-якого місця запитання, відповіді чи коментаря, будь то в попередньо відформатованому блоці коду чи ні.
  • Злиття фрагмента посередині іншого призводить до того, що зовнішній фрагмент вважається двома фрагментами

Найнижчий рахунок виграє!


1
@RobinRyder так, змінився
Beefster

Чи може посада бути старшою за цю проблему чи дорівнює їй, тобто чи можна використовувати фрагменти цього виклику?
Jo King

1
"Як такий, ви не зможете використовувати вбудовані аналізатори регулярних виразів" Чи це означає, що його створено для того, щоб перешкоджати використанню цього для простого ya / ney, або що нам взагалі заборонено використовувати регулярний вираз у своїх відповідях?
користувач0721090601

@guifa розроблено таким чином, що ви не можете просто взяти систему мовного регексу і перевірити, чи він компілює даний регекс. Кожна мова, яку я знаю, підтримує більший набір мета-символів та спеціалізованих груп захоплення, тому вони не відповідають правилам цього набору символів у всіх випадках.
Beefster

1
@ JL2210 Це зробило б два фрагменти: один для початку та один для кінця. Ви можете використовувати один фрагмент до тих пір, поки він не пройде всі тестові випадки, і відповідь / питання / повідомлення старіші за цей виклик
Beefster

Відповіді:


6

Perl 6 , 20 фрагментів

{$_ eq m/[[<-[()*?|\\]>|\\<[()*?|\\]>|'(' <~~>* ')']<[*?]>?|\|]+/}

Спробуйте в Інтернеті!

Фрагменти взяті з:

{$_ eq, m/[, <-[, ()*?, |\\, ]>, |\\, <[, ()*?, |\\, ]>, |, '(' <~~>* ')', <[, *?, ]>, ?|, \|, ]+/, }.

Це здебільшого жадібний підхід (очевидний усіма одним або двома фрагментами символів). Я використовував SymbolHound для пошуку окремих символів, і єдиною реальною оптимізацією був '(' <~~>* ')'фрагмент, який взято з моєї власної відповіді на рекурсивні регекси Perl 6.

Пояснення:

Це в основному перевіряє, чи є вхід рівним жадібною відповідністю дійсного регулярного виразу. Причина, що ми не можемо просто використовувати сам регулярний вираз і додати ^$для позначення кінців, це те, що ми використовуємо рекурсивний регулярний вираз, який би не працював, якби були ^$маркери. Сам регекс:

m/[                             ]+/   # Match one or more times
   [              ]  # Any of 
    <-[()*?|\\]> |     # Not a metacharacter
    \\<[()*?|\\]>      # A metacharacter preceded by a \
    '(' <~~>* ')'      # Brackets surrounding a valid regex
                   <[*?]>?  # Optionally followed by a ? or *
                           | \|    # Or just the | metacharacter

ТІЛ ~~, спасибі!
користувач0721090601

@guifa Так, я дізнався, що через специфікацію P6 , яка містить багато речей, які ще не були належним чином задокументовані. Я підозрюю, що ~~він не з'являється, оскільки він ще не повністю реалізований (наприклад <~~0>), хоча там є й інші приховані дорогоцінні камені.
Джо Кінг,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.