使用.NET正则表达式进行乘法运算

7
在借鉴了polygenelubricants关于正则表达式的有趣尝试后,我现在尝试让.NET正则引擎为我乘法运算。
当然,这没有任何实际价值,仅仅是一个纯理论练习。
到目前为止,我已经得到了下面这个巨大的正则表达式,它应该检查字符串中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

我相信问题出在这一行代码:

(?<b-c>)*

据我所知,在没有匹配的文本的情况下,正则表达式拒绝多次匹配它。 我将正则表达式简化为以下内容:
(1(?<a>))*
(?(a)(?<-a>))*
(?(a)(?!))

这个程序可以通过1,但是无法通过111。我也尝试了(?<-a>)*,但没有任何区别。然而,将其更改为

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

传递了12111222。因此,从匹配""到匹配某些内容会导致正则表达式按预期工作。

回到您最初的正则表达式,我猜想(?<b-c>)*只匹配0-1次,这就解释了为什么在字符串中有一个2可以工作,但是有多个2就失败了。

使用字符串11也失败了,这遵循相同的逻辑,因为这使得整个匹配"",很可能意味着它只匹配一次,导致(?(a)(?!))失败。


0

在Joel的帮助下,我成功让它工作了,稍微修改了算法以避免那些(?<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);

我想提供一个 Ideone 链接,但是我在那里得到的结果与我的不同。也许是因为我正在使用 .NET 4.0 而他们没有?


这仍然在 11 情况下失败,但我还没有找到其他的失败情况。 - Joel Rondeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接