檢查素數的正則表達式[轉]

通常來講,咱們會使用正規表達式來作字符串匹配,今天在網上瀏覽的時候,看到了有人用正則表達式來檢查一個數字是否爲素數(質數),讓我很是感興趣,這個正則表達式如入所示:正則表達式

檢查素數與否的正則表達式算法

要使用這個正規則表達式,你須要把天然數轉成多個1的字符串,如:2 要寫成 「11」, 3 要寫成 「111」, 17 要寫成「11111111111111111」,這種工做使用一些腳本語言能夠輕鬆的完成。shell

一開始我對這個表達式持懷疑態度,但仔細研究了一下這個表達式,發現是很是合理的,下面,讓我帶你來細細剖析一下是這個表達式的工做原理。spa

首先,咱們看到這個表達式中有「|」,也就是說這個表達式能夠分紅兩個部分:/^1?$/ 和 /^(11+?)\1+$/code

  • 第一部分:/^1?$/, 這個部分相信不用我多說了,其表示匹配「空串」以及字串中只有一個「1」的字符串。
  • 第二部分:/^(11+?)\1+$/,這個部分是整個表達式的關鍵部分。其能夠分紅兩個部分,(11+?) 和\1+$,前半部很簡單了,匹配以「11」開頭的並重復0或n個1的字符串,後面的部分意思是把前半部分做爲一個字串去匹配還剩下的字符串1次或屢次(這句話的意思是——剩餘的字串的1的個數要是前面字串1個數的整數倍)。

可見這個正規則表達式是取非素數,要獲得素數還得要對整個表達式求反。經過上面的分析,咱們知道,第二部分是最重要的,對於第二部分,舉幾個例子,blog

 

示例一:判斷天然數8。咱們能夠知道,8轉成咱們的格式就是「11111111」,對於(11+?),其匹配了「11」,因而還剩下「111111」,而\1+$正好匹配了剩下的「111111」,由於,「11」這個模式在「111111」出現了三次,符合模式匹配,返回true。因此,匹配成功,因而這個數不是質數。ci

示例二:判斷天然數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」的整數倍……,而,這正好是咱們須要的算素數的算法。如今你們明白了吧。get

下面,咱們用perl來使用這個正規則表達式不停地輸出素數:(關於perl的語法我就很少說了,請注意表達式前的取反操做符)string

1
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}$

你們不妨本身作作練習,爲何上述的兩個正則表達式能夠判斷方程是否有解。若是沒法參透其中的奧妙的話,你能夠讀讀這篇英文文章

(全文完)

(轉載本站文章請註明做者和出處 酷 殼 – CoolShell.cn ,請勿用於任何商業用途)

相關文章
相關標籤/搜索