Компилировать регулярные выражения (по подстановке)


21

Ваша задача состоит в том, чтобы скомпилировать регулярные выражения ..., указав замену для каждого символа в регулярном выражении.

Регулярные выражения

Регулярные выражения поддерживают эти

REGEX       = (LITERAL REGEX / GROUP REGEX / STAR REGEX / ALTERNATIVE)
LITERAL     = 1 / 0
GROUP       = '(' REGEX ')'
STAR        = (LITERAL / GROUP) '*'
ALTERNATIVE = '('REGEX ('|' REGEX)*')'

Почему только 1 или 0? Это для упрощения. Таким образом, регулярное выражение имеет только следующие символы:

*()|10

Это интерпретируется следующим образом:

  1. * является звездой Клини (повторите левую группу или буквальный 0 или более раз).
  2. | является чередованием (совпадать, если регулярное выражение слева или регулярное выражение справа).
  3. () группировка.
  4. 1 соответствует персонажу 1
  5. 0 соответствует символу 0.

Как скомпилировать?

Вы указываете шесть фрагментов кода: по одному для замены каждого символа регулярного выражения. Например, если ваш ответ:

*: FSAGFSDVADFS
|: GSDGSAG
(: GSDG
): GDSIH
1: RGIHAIGH
0:GIHEBN

Затем вы заменяете каждое регулярное выражение соответствующим фрагментом кода, поэтому:

(0|11)*

превращается в:

GSDGGIHEBNGSDGSAGRGIHAIGHRGIHAIGHGDSIHFSAGFSDVADFS

Что должна делать итоговая программа?

Ваша программа будет:

  1. Возьмите вход.
  2. Выведите истинное значение, если регулярное выражение соответствует целому вводу.
  3. В противном случае выведите ложное значение.

Вход за пределами 01заключен в неопределенное поведение. Ввод может быть пустым.

Дополнительные правила

  1. Для заданного символа регулярного выражения полученный фрагмент всегда должен быть одинаковым.
  2. После этого префикс или суффиксный символ не добавляются.
  3. Регулярное выражение гарантированно не пусто.

счет

Наименее комбинированный фрагмент - победитель. Таким образом, оценка для примера будет рассчитываться следующим образом:

FSAGFSDVADFS+ GSDGSAG+ GSDG+ GDSIH+ RGIHAIGH+GIHEBN

12 + 7 + 4 + 5 + 8 + 6 = 42


Каждый фрагмент должен быть длиной не менее 1 символа?
трихоплакс

Фрагмент может иметь нулевую длину. Редактирование в порядке.
Akangka

Является ли язык RegEx действительным для этого вызова? : P
Loovjo

Я считаю, что у RegEx есть встроенная функция RegEx. Я вынужден сделать это. Я хочу исключить Retina и regex, однако, по словам Мего, это запрещено. Тем не менее, я не знаю об Улитках и друзьях.
Akangka

@ChristianIrwan Интересно, я все еще не уверен, что это даже решаемо в Retina, и даже это, это будет далеко от соревнования.
Мартин Эндер,

Ответы:


7

Улитки , 48 байт

0 -> )0(\0!(l.)(~

1 -> )0(\1!(l.)(~

( -> )0({{(

) -> )0}}(~

| -> )0}|{(

* -> )0),(~

Если бы нам пришлось искать частичные совпадения, а не сопоставлять только полный ввод, это было бы очень просто. 0станет \0, 1станет \1, *станет ,, а другие будут отображаться для себя. Вместо этого есть много махинаций, чтобы предотвратить начало матчей где-то кроме начала или окончания где-то кроме конца. !(l.)это утверждение, которое потерпит неудачу, если начало совпадения находится не в начале ввода. ~соответствует ячейке за пределами ввода, поэтому она добавляется ко всем символам, которые могут находиться в конце регулярного выражения. Если есть следующий символ регулярного выражения, он отменяется числовым квантификатором0который требует, чтобы это соответствовало 0 раз, по существу, комментируя это. Чтобы разрешить *( ,) работать правильно, несмотря на то, что в процессе находится фиктивный тест за пределами допустимых границ, в языке часто используются правила соответствия скобок. Из документации:

Соответствующие пары скобок ()или фигурных скобок {}будут вести себя так, как ожидается (подобно скобкам в регулярном выражении), но также можно опустить половину пары и сделать вывод, согласно следующим правилам. )или }группирует все слева до ближайшей незамкнутой инструкции по открытию группы того же типа ( (или {соответственно) или до начала шаблона, если такового не существует. Он закрывает все незакрытые инструкции по открытию противоположного типа в середине этого диапазона. В противном случае не соответствует (или {закрывается в конце шаблона.

Ясно, как грязь, верно?


Вздох, я забыл, что есть даже соответствующий язык за пределами регулярных выражений. Хорошая работа, но извините, нет голосов (тоже нет голосов)
Akangka

@ChristianIrwan на этом сайте есть целая задача по разработке 2-х подходящих языков, большинство из которых имеет 1-й вырожденный тип использования. codegolf.stackexchange.com/questions/47311/…
Спарр

7

CJam, 151 байт

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

Строки соответствуют символам 01(|)*(в этом порядке). Попробуйте онлайн!

При этом не используется встроенное регулярное выражение или другие типы сопоставления с образцом. На самом деле, CJam не имеет ни одной из этих функций. Вместо этого он начинается с регулярного выражения, которое он представляет, и строит все возможные строки, которые ему могут соответствовать, чтобы наконец проверить, является ли пользовательский ввод одной из них.

Тестовые прогоны

Далее используется программа, которая читает регулярное выражение из STDIN, заменяет каждый из его символов соответствующим фрагментом и, наконец, оценивает сгенерированный код, чтобы определить, соответствует ли он вводу, указанному в аргументе командной строки.

$ cat regex.cjam
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

"N%ers~
$ cjam regex.cjam '' <<< '(|)'
1
$ cjam regex.cjam '0' <<< '(|)'
0
$ cjam regex.cjam '' <<< '0(|)'
0
$ cjam regex.cjam '0' <<< '0(|)'
1
$ cjam regex.cjam '' <<< '(0|11)*'
1
$ cjam regex.cjam '0' <<< '(0|11)*'
1
$ cjam regex.cjam '11' <<< '(0|11)*'
1
$ cjam regex.cjam '011011000' <<< '(0|11)*'
1
$ cjam regex.cjam '1010' <<< '(0|11)*'
0

К сожалению, это не особенно быстро. Он будет задыхаться довольно быстро, если на входе будет более 9 символов или более одной звезды Клини в регулярном выражении.

Ценой 5 дополнительных байтов - в общей сложности 156 байтов - мы можем генерировать более короткие строки для сопоставления потенциального ввода и дедупликации их. Это не меняет работу кода; это просто делает его более эффективным.

$ cat regex-fast.cjam 
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+eas,)m*:sSf-L|\"T

"N%ers~
$ cjam regex-fast.cjam '0101001010' <<< '(01|10)*'
0
$ cjam regex-fast.cjam '011001101001' <<< '(01|10)*'
1
$ cjam regex-fast.cjam '0' <<< '(0*1)*'
0
$ time cjam regex-fast.cjam '101001' <<< '(0*1)*'
1

У меня все еще есть идея, как я могу сделать это короче и / или быстрее. Я добавлю объяснение, когда я буду доволен результатами.
Деннис

Кажется, `-escaping of the в шаблоне есть «лишнее » *. Несмотря на это, я не мог заставить эту программу принимать какие-либо входные данные, даже для простейшего случая, когда регулярное выражение состоит только из 0(см. Тест в онлайн-интерпретаторе ). Я делаю это неправильно?
Matz

1
@matz Мой код использует аргументы командной строки, которые не реализованы в этом интерпретаторе. Попробуйте это вместо этого.
Деннис
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.