Regexercise:阶乘

时间:2010-09-20 00:57:07

标签: regex factorial nested-reference balancing-groups

  

这是StackOverlow的一项实验性新功能:通过解决各种经典问题来锻炼你的正则表达式肌肉。没有一个正确的答案,事实上我们应该收集尽可能多的正确答案,只要它们具有教育价值。接受所有口味,但请记录清楚。尽可能实用,提供测试用例/片段来证明模式“有效”。

我们怎样才能找到一个数字 x 是否是使用正则表达式的阶乘?

奖励:如果模式可以确定 x = n!,它还可以找到 n 吗?

2 个答案:

答案 0 :(得分:3)

Java,具有无限长度的lookbehind和嵌套引用(see also on ideone.com):

import java.util.regex.*;

class Factorial {
static String assertPrefix(String pattern) {
   return "(?<=(?=^pattern).*)".replace("pattern", pattern);
}
public static void main(String[] args) {
   final Pattern FACTORIAL = Pattern.compile(
      "(?x) (?: inc stepUp)+"
         .replace("inc", "(?=(^|\\1 .))")
         //                      1

         .replace("stepUp", "(?: ^. | (?<=(^.*)) (?=(.*)) (?: notThereYet \\2)+ exactlyThere )")
         //                                2          3

         .replace("notThereYet", "(?:  (?=((?=\\3) .  |  \\4 .)) (?=\\1(.*)) (?=\\4\\5)  )")
         //                                           4                  5

         .replace("exactlyThere", "measure4 measure1")
            .replace("measure4", assertPrefix("\\4(.*)"))
            .replace("measure1", assertPrefix("\\1\\6"))
   );

   for (int n = 0; n < 1000; n++) {
      Matcher m = FACTORIAL.matcher(new String(new char[n]));
      if (m.matches()) {
         System.out.printf("%3s = %s!%n", n, m.group(1).length() + 1);
      }
   }
}
}

答案 1 :(得分:1)

使用.NET平衡组,在C#(see also on ideone.com)中:

var r = new Regex(@"(?xn) 

^(
   (
     ( ^.
     | (?=  (?<temp-n> .)+ )
       (?<= (?<fact>  .+)  )
       (?<n-temp> \k<fact> )+?
       (?(temp) (?!))
     )
     (?<n>)
   )+
 )$

");

for (int x = 0; x < 6000; x++) {
   Match m = r.Match("".PadLeft(x));
   if (m.Success) {
      Console.WriteLine("{0,4} = {1}! ", x, m.Groups["n"].Captures.Count);
   }
}

注意:

ideone.com使用的.NET版本似乎在平衡组中有一个错误,导致上述代码段中不必要的重复+?。在较新的版本中,简单的贪婪+就足够了。另见:Backtracking a balancing group in a greedy repetition may cause imbalance?