1. 程式人生 > 實用技巧 >密碼驗證

密碼驗證

今天刷到了一道華為的機考題——密碼驗證。題目描述如下:
密碼要求:
1.長度超過8位
2.包括大小寫字母.數字.其它符號,以上四種至少三種
3.不能有相同長度大於2的子串重複

輸入描述:
一組或多組長度超過2的子符串。每組佔一行

輸出描述:
如果符合要求輸出:OK,否則輸出NG

輸入示例:
021Abc9000
021Abc9Abc1
21ABC9000
021$bc9000


輸出示例:
OK
NG
NG
OK

這道題乍一看沒什麼特別的,但是今天自己做的時候發現裡面真的暗藏玄機(也是因為個人水平有限hh)。接下來就簡單說下自己在做這道題遇到的困惑和解決方法。

一、標準輸入問題

看他的輸入輸出示例,並沒有像之前做過的題一樣,有一個固定的可輸入輸入行數,當時第一反應就是是不是題出錯了hh...

後來通過看別人的程式碼,才知道原來還有標準輸入輸出這一說。。。

具體而言,我們可以用標準輸入來解決這一問題:

import sys
for line in sys.stdin:
    line = line.strip()

其中的line就是輸入的每行字串。但是還有個問題就是,不知道怎麼去停止輸入過程?

自己查了下可以用Ctrl+D來停止輸入過程。

二、用正則表示式來實現密碼判別

我們可以看到密碼要求的前兩個(1.長度超過8位,2.包括大小寫字母.數字.其它符號,以上四種至少三種)還是比較容易實現的。

程式碼如下:

for line in sys.stdin:

    line 
= line.strip() #1 if len(line) <= 8: print("NG") continue #2 count = 0 if re.search('[0-9]',line): count += 1 if re.search('[a-z]',line): count += 1 if re.search('[A-Z]',line): count += 1 if re.search('[^a-zA-Z0-9]',line): count += 1 if count < 3:
print("NG") continue

注意這裡不能用W來匹配除了大小寫字母.數字的其他符號,因為W還把下劃線去掉了。

這道題的關鍵在於如何判斷第三個密碼要求(不能有相同長度大於2的子串重複)。

這裡比較容易實現和理解的就是用迴圈判斷的方法來判斷是否有子串重複:

def passwd_rep(str):
    # 一次拿出一個長度為3的子串,則只需迴圈len(str)-3+1次即可遍歷完字串    
    for i in range(len(str)-2):
        # 如果相同子串的數量大於1,即子串重複,返回False
        if str.count(str[i:i+3]) > 1:
            return False
    return True

但是同樣的我看到有人用正則表示式來判斷:

re.search(r'.*(...)(.*\1)', line)

乍一看還是很漂亮的。

但是這是我第一次接觸到正則表示式用‘\1’的方法。。。好吧我確實太菜了。

如果有同樣對這個用法不太瞭解的同學,我在這裡為大家簡單介紹一下:

\1是用來匹配第一個分組即第一個括號裡面匹配的內容,利用這個特性可以查詢是否有重複元素。

推而廣之,\1 \2 ... \9 分別是用來匹配第1,2,...,9個分組裡面的內容。

另外,關於匹配時是否用括號,也是一門學問,有興趣的同學可以看這篇博文:

https://blog.csdn.net/qq_32925781/article/details/83315468

後續有機會的話我也會自己寫一篇總結。