正则表达式按3计数

时间:2013-12-27 06:06:10

标签: regex string-matching digit

我正在教自己正则表达式,并找到了一个帮助我找到更多应用程序的测验网站,并帮助我扩展了他们的工作方式。

我发现了一个问题,要求我形成一个正则表达式来匹配10位数的3位数。我能想到这样做的唯一方法是让正则表达式识别数字的值并能够以数学方式操纵它们。这怎么可能?

换句话说,正则表达式匹配

0003
0006
0351
1749

但不匹配

0005
0011
0361
4372

2 个答案:

答案 0 :(得分:3)

首先你需要从一个数字可以除以三的规则开始,当且仅当它的数字之和可以被3整除时(证明这需要一点理论,但它有助于看到9,99, 999等都是三的倍数,因此1,10,100,1000等等都会在除以3时对数字的余数贡献相同的数量。

然后,注意有三种数字:

  • 三的倍数:0,3,6和9.这些相当于 0 (mod 3)。
  • 超过三的倍数:1,4和7.这些相当于 1 (mod 3)。
  • 两个乘以三的倍数:2,5和8.这些相当于 -1 (mod 3)。通常这个类名为 2 ,但-1对我们更有用。因为1 + 2 = 0(mod 3),-1是2的合法名称。

然后,数字0,3,6和9是三的倍数。如果我们在任何地方添加 0 类中的任意数字,则数字仍然是三的倍数(因此33,999和963都是三的倍数)。如果我们在任何地方添加 1 类的数字,我们需要添加另一个数字 -1 ,或者再添加两个数字 1 将余数恢复为0.同样,如果我们在任何地方添加 -1 类的数字,我们需要添加另一个数字 1 ,或者再添加两个数字类 -1 的数字将余数恢复为0。

这是wcp的答案,格式为perl /x正则表达式,以提高可读性:

/
(   [0369] # 0
  | [147] [0369]* [258] # 1 + 0 + -1 = 0
  | (   [258] # -1
      | [147] [0369]* [147] # 1 + 0 + 1 = -1
    ) # -1
    (   [0369] # 0
      | [258] [0369]* [147] # -1 + 0 + 1 = 0
    )* # 0
    (   [147] # 1
      | [258] [0369]* [258] # -1 + 0 + -1 = 1
    ) # 1 ... -1 + 0 + 1 = 0
)+
/x

正则表达式匹配余数为0的数字组。第一个分支仅匹配类 0 的数字;第二个分支匹配剩余部分为1然后又回到0的组;并且第三个分支匹配其余部分下降到-1然后又回到0的组。在构造方式上有一些聪明(我认为一个不太高尔夫的正则表达式将有五个主要分支而不是三个,但是评论应该足以让你遵循它。

答案 1 :(得分:2)

就像@Jerry在评论中说的那样,你可以使用它:

([0369]|[147][0369]*[258]|([258]|[147][0369]*[147])([0369]|[258][0369]*[147])*([147]|[258][0369]*[258]))+

更短