查抄素数的正则表达式

一般来说,我们会利用正规表达式来做字符串匹配,本日在网上欣赏的时候,看到了有人用正则表达式来查抄一个数字是否为素数(质数),让我很是感乐趣,这个正则表达式如入所示:


 
查抄素数与否的正则表达式


要利用这个正法则表达式,你需要把自然数转成多个1的字符串,如:2 要写成 “11”, 3 要写成 “111”, 17 要写成“11111111111111111”,这种事情利用一些剧本语言可以轻松的完成。

一开始我对这个表达式持猜疑立场,但仔细研究了一下这个表达式,发明长短常公道的,下面,让我带你来细细分解一下是这个表达式的事情道理。


首先,我们看到这个表达式中有“|”,也就是说这个表达式可以分成两个部门:/^1?$/ 和 /^(11+?)\1+$/


第一部门:/^1?$/, 这个部门相信不消我多说了,其暗示匹配“空串”以及字串中只有一个“1”的字符串。

第二部门:/^(11+?)\1+$/,这个部门是整个表达式的要害部门。其可以分成两个部门,(11+?)\1+$,前半部很简朴了,匹配以“11”开头的并反复0或n个1的字符串,后头的部门意思是把前半部门作为一个字串去匹配还剩下的字符串1次或多次(这句话的意思是——剩余的字串的1的个数要是前面字串1个数的整数倍)。


可见这个正法则表达式是取非素数,要获得素数还得要对整个表达式求反。通过上面的阐明,我们知道,第二部门是最重要的,对付第二部门,举几个例子,


示例一:判定自然数8。我们可以知道,8转成我们的名目就是“11111111”,对付(11+?),其匹配了“11”,于是还剩下“111111”,而\1+$正好匹配了剩下的“111111”,因为,“11”这个模式在“111111”呈现了三次,切合模式匹配,返回true。所以,匹配乐成,于是这个数不是质数。


示例二:判定自然数11。转成我们需要的名目是“11111111111”(十一个1),对付(11+?),其匹配了“11”(前两个1),还剩下“111111111”(九个1),而\1+$无法为“11”匹配那“九个1”,因为“11”这个模式并没有在“九个1”这个串中正好呈现N次。于是,我们的正则表达式引擎会实验下一种要领,先匹配“111”(前三个1),然后把“111”作为模式去匹配剩下的“11111111”(八个1),很明明,那“八个1”并没有匹配“三个1”多次。所以,引擎会继承向下实验……直至实验所有大概都无法匹配乐成。所以11是素数。


通过示例二,我们可以获得这样的等价数算算法,正则表达式会匹配这若干个1中有没有呈现“二个1”的整数倍,“三个1”的整数倍,“四个1”的整数倍……,而,这正好是我们需要的算素数的算法。此刻各人大白了吧。


下面,我们用perl来利用这个正法则表达式不断地输出素数:(关于perl的语法我就不多说了,请留意表达式前的取反操纵符)

perl -e'$|++;(1 x$_)!~/^1?$|^(11+?)\1+$/&&print"$_ "while ++$_'

别的,让我们来触类旁通,按照上述的这种要领,我们甚至可以用正则表达式来求证某方法是否有解,如:

二元方程:17x + 12y = 51   判定其是否有解的正则表达式是:^(.*)\1{16}(.*)\2{11}$

三元方程:11x + 2y + 5z = 115 判定其是否有解的正则表达式是:^(.*)\1{10}(.*)\2{1}(.*)\3{4}$

各人不妨本身做做操练,为什么上述的两个正则表达式可以判定方程是否有解。假如无法参透个中的玄妙的话,你可以读读这篇英文文章

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/7775.html