Какое регулярное выражение Perl может соответствовать непрерывному подмножеству цифр 12345? - PullRequest
6 голосов
/ 24 октября 2010

Мне бы хотелось, чтобы регулярное выражение Perl соответствовало любому смежному подмножеству строки '12345'.

Возможно, у меня просто замораживание мозга, но это мой тестовый код и лучший на текущий момент регулярный код.Я могу понять, как исправить ситуацию, добавив альтернативы, но мне интересно, какую изящную альтернативу мне не хватает.[ Мне специально не нужны захваты для цифр;Я оставил образец регулярного выражения без скобок без захвата, чтобы сделать его немного менее загроможденным. ]

Контрольный пример:

use strict;
use warnings;

my @good = qw( 1 12 123 1234 12345 2 23 234 2345 3 34 345 4 45 5);
my @bad  = qw( 0 6 13 134 1345 145 15 124 1245 125 1235 24 245 25
               35 21 32 43 54 543 5432 54321);

my $qr = qr/^(1?(2?(3(4(5)?)?)?)?)$/;   # 3 'good', 3 'bad' failures
#my $qr = qr/^(1?(2(3(4(5)?)?)?)?)$/;   # 6 'good' failures.
my $fail = 0;

foreach my $opt (@good)
{
    printf "GOOD %d: $opt - missed by regex\n", ++$fail if ($opt !~ /$qr/);
}

foreach my $opt (@bad)
{
    printf "BAD %d: $opt - allowed by regex\n", ++$fail if ($opt =~ /$qr/);
}

print(($fail == 0) ? "PASS\n" : "FAIL\n");

Пример выходных данных:

Кейс1 (закомментировано):

GOOD 1: 3 - missed by regex
GOOD 2: 34 - missed by regex
GOOD 3: 345 - missed by regex
GOOD 4: 4 - missed by regex
GOOD 5: 45 - missed by regex
GOOD 6: 5 - missed by regex
FAIL

Случай 2 (активный):

GOOD 1: 4 - missed by regex
GOOD 2: 45 - missed by regex
GOOD 3: 5 - missed by regex
BAD 4: 13 - allowed by regex
BAD 5: 134 - allowed by regex
BAD 6: 1345 - allowed by regex
FAIL

Итак, вы можете написать хорошее простое симметричное регулярное выражение, которое соответствует тому, что я хочу, а не тому, что яне так?


Это регулярное выражение позволяет пройти тестовый пример, но не так элегантно, как я надеялся:

my $qr = qr/^((1?(2(3(4(5)?)?)?)?)|(3?(4(5)?)?)|5)$/;

Тестовый пример с решением Джастина

use strict;
use warnings;

my @good = qw( 1 12 123 1234 12345 2 23 234 2345 3 34 345 4 45 5);
my @bad  = qw( 0 6 13 134 1345 145 15 124 1245 125 1235 24 245 25
               35 21 32 43 54 543 5432 54321 11 122 1233 1223 12234);

#my $qr = qr/^(1?(2?(3(4(5)?)?)?)?)$/;   # 3 'good', 3 'bad' failures
#my $qr = qr/^(1?(2(3(4(5)?)?)?)?)$/;    # 6 'good' failures.
#my $qr = qr/^((1?(2(3(4(5)?)?)?)?)|(3?(4(5)?)?)|5)$/;  # Passes

# Ysth's solution - passes
#my $qr = qr/^[12345](?:(?<=1)2|(?<=2)3|(?<=3)4|(?<=4)5)*$/;

my $fail = 0;

foreach my $opt (@good)
{
    printf "GOOD %d: $opt - missed by regex\n", ++$fail if ('12345' !~ /$opt/);
    #printf "GOOD %d: $opt - missed by regex\n", ++$fail if ($opt !~ /$qr/);
}

foreach my $opt (@bad)
{
    printf "BAD %d: $opt - allowed by regex\n", ++$fail if ('12345' =~ /$opt/);
    #printf "BAD %d: $opt - allowed by regex\n", ++$fail if ($opt =~ /$qr/);
}

print(($fail == 0) ? "PASS\n" : "FAIL\n");

Ответы [ 4 ]

12 голосов
/ 24 октября 2010

Обратный матч:

'12345' =~ /$opt/
7 голосов
/ 24 октября 2010

Вот пересмотренная версия идеи Джастина:

index('12345', $opt) >= 0;

Или, если вам нужно исключить пустую строку

index('12345', $opt) >= 0 and length $opt;

Таким образом, вам не нужно проверять $opt для метасхем регулярных выражений. Я не уверен, какая версия будет быстрее.

1 голос
/ 24 октября 2010
/^[12345](?:(?<=1)2|(?<=2)3|(?<=3)4|(?<=4)5)*\z/

Извините, дважды ошибся. Это должно сделать это. Однако точный список всех возможных совпадений будет быстрее.

0 голосов
/ 24 октября 2010

Хотите что-то лучше, чем

/\b(1|12|123|1234|12345|2|23|234|2345|3|34|345|4|45|5)\b/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...