Умножение с помощью регулярных выражений .NET - PullRequest
7 голосов
/ 24 сентября 2010

В духе полигенных смазочных материалов 'попытки делать глупые вещи с регулярными выражениями, В настоящее время я пытаюсь заставить движок .NET regex размножаться для меня.

Это, конечно, не имеет никакой практической ценности и подразумевается как чисто теоретическое упражнение.

Пока что я дошел до этого монстра, который должен проверить, равно ли число 1, умноженное на число 2, равно 3 в строке.

Regex regex = new Regex(
@"
^
(1(?<a>))*  # increment a for each 1
(2(?<b>))*  # increment b for each 2
    (?(a)   # if a > 0
        (                   
            (?<-a>)             # decrement a
            (3(?<c-b>))*        # match 3's, decrementing b and incrementing c until
                                # there are no 3's left or b is zero
            (?(b)(?!))          # if b != 0, fail
            (?<b-c>)*           # b = c, c = 0
        )
    )*      # repeat
(?(a)(?!))  # if a != 0, fail
(?(c)(?!))  # if c != 0, fail
$
", RegexOptions.IgnorePatternWhitespace);

К сожалению, это не работает, и я в недоумении, почему. Я прокомментировал это, чтобы показать вам, что я думаю, двигатель должен делать, но я могу быть здесь. Примеры вывода:

regex.IsMatch("123") // true, correct
regex.IsMatch("22") // true, correct
regex.IsMatch("12233") // false, incorrect
regex.IsMatch("11233"); // true, correct

Любые мысли приветствуются!

Ответы [ 2 ]

1 голос
/ 25 сентября 2010

Я почти уверен, что проблема в этой строке:

(?<b-c>)*

Из того, что я могу сказать, без текста для сравнения, Regex отказывается сопоставлять его более одного раза.Я уменьшил регулярное выражение до следующего:

(1(?<a>))*
(?(a)(?<-a>))*
(?(a)(?!))

, который проходит на 1, но не на 111.Также попробовал (?<-a>)*.Нет разницы.Однако, изменение его на

(1(?<a>))*
(?(a)((?<-a>)(2(?<b>))(?<-b>)))*
(?(a)(?!))

проходит как 12, так и 111222.Таким образом, переход от совпадения "" к совпадению с чем-либо приводит к тому, что регулярное выражение работает должным образом.

Возвращаясь к исходному регулярному выражению, я предполагаю, что (?<b-c>)* соответствует только 0-1 разу,это объясняет, почему работает один 2 в вашей строке, но иметь более одного не удается.

Использование строки 11 также не работает, что соответствует той же логике, что и полное совпадение "",что, скорее всего, означает, что он совпадает только один раз, что приводит к сбою (?(a)(?!)).

0 голосов
/ 27 сентября 2010

С помощью ввода Джоэля я смог заставить его работать, слегка изменив алгоритм, чтобы избежать этих (?<b-c>)* строк.

Вот:

Regex regex = new Regex(
@"
^
(1(?<a>))*  # increment a for each 1
(2(?<b>))*  # increment b for each 2
    (?(a)   # if a > 0
         (
            (?<-a>)             # decrement a
            (?(b)               # if b > 0
                (                                       
                    (3(?<c-b>))*        # match 3's, decrementing b and incrementing c until
                                        # there are no 3's left or b is zero
                    (?(b)(?!))          # if b != 0, fail
                )
                |                       # else ( b = 0 )
                (
                    (3(?<b-c>))*        # match 3's, decrementing c and incrementing b until
                                        # there are no 3's left or c is zero
                    (?(c)(?!))          # if c != 0, fail
                )
            )
        )
    )*      # repeat
(?(a)(?!))  # if a != 0, fail
$
", RegexOptions.IgnorePatternWhitespace);

Я хотел бы дать ссылку на идеон, но результат, который я получаю, отличается от моего.Может быть, потому что я использую .NET 4.0, а они нет?

...