正则大挑战
正則大挑戰(zhàn)
最近發(fā)現的一個網站,關于正則的練習網站::鏈接,大概16題,從Easy到Hard,覆蓋的面很廣,有評分,也有很多大佬追求極致評分,頁面大概長下面這樣,讓我們現在開始吧。
因為網站改版,現在已經不顯示分數了,大致的評分機制如下:
Points = (需求列表匹配數 * 10) - (不允許列表匹配數 * 10) - 表達式字符數
例如:foo的字符數是3,需求列表匹配數=42,不允許列表匹配數=21,代入上面的公式:得到的分數是207207207分
下面的部分是Classic部分
1.Warmup
Type a regex in the box.
- 仔細觀察,左側的字符都出現了foo這字符,右側則沒有,因此直接填入foo可以解,得分為207207207分
2.Anchors
You are deducted one point per character you use, and ten if you match something you shouldn’t.
- 左側的每個字符都是以ick結尾的,使用ick$,得分206206206分,如果還想要精簡一下的話,k$也可以做到匹配,得分能到208208208分
緊接著,根據上一題的做法,給了下面這道題,但是不允許有$
- 考慮使用\b這個匹配,\b 斷言此位置為單詞邊界:(^\w|\w$|\W\w|\w\W),u\b可以解本題,得分207207207分
3.Ranges
The test vectors were generated by grepping /usr/dict/words. Can you tell?
- 考察的是字母的范圍,觀察下來,左側的字母都是a-f之間的,右側不需要匹配的,則超出了這個范圍,^[a-f]*$可以解,要求a-f的字符出現了0次以上,得分202202202分
4.Backrefs
This doesn’t really work as a tutorial. Not really clear what you’re supposed to do here.
- 觀察下來是xxx......xxx這樣的形式,如allochirally,all在前面出現過一次,在后面又出現了一次,這種結構很容易使用反向引用解決,(...).*\1可以解決,得分201201201分,其中\(zhòng)1匹配與捕獲組1st最近匹配的相同的文本,也就是前面的那個括號
5.Abba
Let’s pretend this one is not a rehash of the last one.
-
這一題要求的是不能匹配形如abba這樣結構的字符,如右側的anallagmatic這個單詞,alla便是這種結構,需要把這種結構的字符全部排除掉
-
使用負向零寬先行斷言,可以篩選出左側匹配上的,(?!(.)(.)\2\1),但是右側的不能篩選出來,而且需要排除掉這種串****xoox****,只需要在前后補字符并把這段能匹配上的字符全部排除掉,^(?!.*(.)(.)\2\1.*)為最終解,這個字符是19個,總的是43個單詞,扣除右邊不要的22個單詞,得分是210-19=191191191分
-
在本題中,去掉最后的字符匹配也能通過,^(?!.*(.)(.)\2\1),得分來到193193193
-
還看到多大神的一種解法^(?!.*(.)\1)相當于強制篩選abba中間的結構,而不管前后的a,然而輸入進去后,發(fā)現左側有兩個應該要匹配的字符匹配不上,這時候觀察了下這個兩個字符,都有ef兩個相連的字符,^(?!.*(.)\1)|ef可以解本題,得分來到195195195分
6.A man, a plan
You’re allowed to cheat a little. Even in hard mode, words will be no longer than 13 characters.
- 本題是要找這種回文結構,如deedeed,civic,也就是常說的偶回文,奇回文,寫出(.)(.).?\2\1后發(fā)現,右側有一個字符沒有被排除掉,觀察左側的字符,可以往后再多多加一個字符強制提前結束,寫出這樣的正則:(.)(.).?\2\1.?$,得分為175175175分
- 但是本題題干部分給出了「cheat」的字眼,那我們就不客氣了,精簡到只反向引用一個字符,寫出^(.).*\1$,但是如下圖,右側有一個單詞沒有被排除掉,采用「cheat」的方式,排除掉這個單詞^(.)[^p].*\1$,得分來到177177177
7.Prime
- 題目要求篩選出長度是Prime也就是諸如2、3、5、7、11、13、17等這樣的質數,的字符串,字符都是x組成的,一開始我看出了要判斷括號的里的數字,其實是題面省略了x的個數,比如說xx...(17)..xx表示這一行x出現了17次,也就是質數,右側的是非質數
- 做法也很巧妙,主體思想是要篩掉右側這種非質數,也就是諸如4、6、8、9、10、12、14、15、16等這樣的數,了解埃篩(埃拉托斯特尼篩法)的話,這一題就很容易解答,首先發(fā)現2的倍數諸如4、6、8、10、12等這樣的數不是質數、3的倍速6、9、12、15、18等這樣的不是質數,同理對于5,7等數的倍數也不是質數,只需要使用反向引用可以達到翻倍的效果
- (..+)中+表示出現一次或者無數次,也就是說,某個字符出現2、3、4、5等次數,(..+)\1+,使用反向引用對前面匹配到的捕獲組進行重復,+表示至少1次,通過這樣的方式,保留了作為2、3、4、5這樣的基本數,篩選出了2的倍數,3的倍數、4的倍數、5的倍數,加一個否定環(huán)視?!(..+)\1+,就能匹配到右邊,而左邊沒匹配
- 接著,提供一個反選,可以匹配到左邊,曬出掉右邊^(qū)(?!(..+)\1+$),KaTeX parse error: Undefined control sequence: \1 at position 41: …是可以的:`^(?!(xx+)\?1?+)`
8.Four
You can get an extra point by ignoring the name of this level.
- 需要匹配這種x*x*x*x*結構,只需要反向引用第一個字符,整體3次即可,(.)(.\1){3},得分199199199
9.Order
Cheat
- 這一題題面已經給了可以「cheat」,看了下大佬的解,我不說話了:^.{5}[^e]?$,左邊的字符都是5個,右邊的字符都含有e這個字符,排除掉
10.Triples
Multiples of 7 are left as an exercise for the reader.
-
這一題之前的文章詳細介紹過怎么使用自動狀態(tài)機構造符合3的倍數的正則:正則表達式如何匹配3的倍數?
-
看了下牛人給出的答案,沒什么營養(yǎng),大體就是面向測試寫正則:00($|3|6|9|12|15)|4.2|.1.+4|55|.17,這種方式應該是一種作弊手段,且不太可能被推廣,7的倍數也可以使用上面鏈接講到的方式去完成
11.Glob
- 題意是想匹配xxx mathchs yyy這樣的結構,可能xxx中有*,需要替換掉對應的字符,位置順序必須一致,看了眼答案:ai|c$|^p|[bcnrw][bnopr],是觀察出來的結果
12.Balance
This one is also impossible, but there’s a finite number of test cases.
-
題意是要篩選出正確的括號對,^(<(..(?!<.>$))*>)*$ ,這里面用到了循環(huán)捕獲組,只捕獲最后一次匹配。在循環(huán)捕獲組外層加一個括號以獲取所有結果,或使用非捕獲組如果您對捕獲數據不感興趣的話,這其中也使用了否定型順序環(huán)視(?!<.>$),上面的結果不足以通過所有的case,最后補了一個.{37},排除掉了例外的情況,^(<(..(?!<.>$))*>)*$|.{37}是最終的答案
-
括號配對,對于正則是一個非常大的難題,正則文法的定義先天就不是遞歸的。現在用的加強的正則表達式,盡管加入了反向引用、計數、前瞻后瞻等高級功能,只是在引擎層面新增了功能。
13.Powers
- 這題和第7題Prime很像,想要的匹配的是1、2、4、8、32、64、128等這樣2的冪的數量的字符串,3、5、7等這種不應該出現,這些長度的字符串有個特點,可以表示成2n+1,可以寫出^(.(..)+)$這種形式的,可以篩選掉部分,但是401、1025這種長度的還是沒有篩選掉,對這些不符合的數做因式分解,28=7*2*2, 48=3*2*2*2*2, 160=5*2*2*2*2*2, 600=75*2*2*2,也就是說都是(2n+1)*pow(2, m)
- 也就是說,加一個反向引用可以達到倍數的效果,再把這些結構的字符長度的全部篩選掉,答案是:^(?!^(.(..)+)\1*$)
14.Long count
- 又一個反向引用的例子,((.+)0\2+1){8},這段是觀察后的結果,大體意思是把x0x1這種結構重復8次,當然\2+匹配的到的(.+)可以是0次
15.Alphabetical
To save typing the input will only use the characters a/e/n/r/s/t, even in hard mode.
- 看了下答案.r.{32}r|a.{10}te|n.n..,三段的正則,應該是根據目標集找單詞的規(guī)律的,好吧,這題我沒看懂~
16.Powers 2
Or 3
- 想要篩選掉不是3的冪的數,也就是篩選出1 、3、9、27、81這種、篩選掉2、4、5、6、7、8這種不是3的冪的數,和13題Powers類似,需要考慮篩選掉3n+1,3n+2的倍數,因為所有數mod3只有只有三種數0、1、2排除掉后兩種
- ^(?!((xxx)+x|xx)\1*$),里面括號可以篩選出3n+1,3n+2這樣的數,最后反選掉
下面的部分是Teukon部分
17.Subtraction
- 題目要求篩選出正確的等式
- ^(.+)(.+) - \1 = \2$很好理解,第一部分的字符拆成兩個部分,分別給到第一個反向引用和第二個反向引用
18.Typist
With apologies to Dr. Dvorak.
- 找字符的規(guī)律:^[adresbtcfxzgvw]+$
19.Addition
Beauty in symmetry.
- 和17題Subtraction類似,處理方式是將 = 號左右兩邊的+號當成一個組的字符來看,^(.*)(.*)(.*) = \3\2\1$ ,左邊當成一個整體來看,反選掉不符合等式的結果
20.Anyway
Old MacDonald had a farm…
- 大神的寫法:^[aeiouy]?(.[aeiouy])+[^aeiou]?$
21.Tic-tac-toe
Don’t forget the horizontals.
- 找的字符串的規(guī)律:XXX|OOO|([OX])...\1...\1|X..X..X|X....X....X,能篩選出來
總結
- 后面還有題目,我沒寫完,有機會再發(fā)第二期吧~
Reference
- https://gist.github.com/jonathanmorley/8058871
延伸閱讀
-
正則表達式漫談
-
正則表達式如何匹配3的倍數?
個人主頁
- 個人主頁
總結
- 上一篇: 国内自主研发的游戏引擎一览
- 下一篇: 导入项目运行报错:Error start