密码验证——标准输入
今天刷到了一道华为的机考题——密码验证。题目描述如下:
密码要求:
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
后续有机会的话我也会自己写一篇总结。