这是 StackOverlow 的一个实验性新功能:通过解决各种经典问题来锻炼你的正则表达式肌肉。没有一个正确的答案,事实上我们应该收集尽可能多的正确答案,只要它们具有教育价值。接受所有口味,但请清楚记录。尽可能提供测试用例/片段来证明该模式“有效”。
我们如何使用正则表达式找到数字x是否是阶乘?
奖励:如果模式可以确定x = n!, 它也能找到n吗?
这是 StackOverlow 的一个实验性新功能:通过解决各种经典问题来锻炼你的正则表达式肌肉。没有一个正确的答案,事实上我们应该收集尽可能多的正确答案,只要它们具有教育价值。接受所有口味,但请清楚记录。尽可能提供测试用例/片段来证明该模式“有效”。
我们如何使用正则表达式找到数字x是否是阶乘?
奖励:如果模式可以确定x = n!, 它也能找到n吗?
Java,具有无限长度的lookbehind和嵌套引用(另见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);
}
}
}
}
使用 .NET 平衡组,在 C# 中(另见 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 版本似乎在平衡组中存在错误,+?
导致上述片段中不情愿的重复成为必要。在较新的版本中,简单的贪心+
可能就足够了。另请参阅:在贪婪重复中回溯平衡组可能会导致不平衡?