Problem
Write a program to return True
, if a string is a strong password.
A password is considered strong if below conditions are all met:
- It should have at least 6 characters and at most 20 characters.
- It must contain at least one lowercase, one uppercase and one digit.
- It must NOT contain three repeating characters in a row ("...aaa..." is weak, but "...aa...a..." is fine, assuming other conditions are met).
Code
I've solved a similar problem to LeetCode Strong Password Checker. If you would like to review the code or add other methods or provide any change/improvement recommendations please do so! Thank you!
def strong_password_match(s: str) -> bool:
"""Returns a boolean if a password is correct"""
import re
if re.match(
r'^(?!.*([a-z])\1\1)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[A-Za-z0-9]{6,20}$', s) is not None:
return True
return False
def strong_password_search(s: str) -> bool:
"""Returns a boolean if a password is correct"""
import re
if re.search(
r'^(?!.*([a-z])\1\1)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[A-Za-z0-9]{6,20}$', s) is not None:
return True
return False
def strong_password_findall(s: str) -> bool:
"""Returns a boolean if a password is correct"""
import re
if re.findall(
r'^(?!.*([a-z])\1\1)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[A-Za-z0-9]{6,20}$', s) != []:
return True
return False
if __name__ == '__main__':
# ---------------------------- TEST ---------------------------
import timeit
import cProfile
DIVIDER_DASH_LINE = '-' * 50
GREEN_APPLE = '\U0001F34F'
RED_APPLE = '\U0001F34E'
test_methods = (
("re.match", strong_password_match),
("re.search", strong_password_search),
("re.findall", strong_password_findall),
)
test_inputs = ('abcAb1', 'abcAb1abcAb1abcAb100',
'abcAb1abcAb1abcAb10111', 'aaaAb1abcAb1abcAb100')
# --------------------------------- PROFILING AND BANCHMARK SETTINGS --------------------------------------
NUMBER_OF_RUNS = 1
CPROFILING_ON = False
BENCHMARK_ON = True
for description, method in test_methods:
print((GREEN_APPLE + RED_APPLE) * 5)
for test_input in test_inputs:
if CPROFILING_ON:
print(f'{description} cProfiling: ', cProfile.run("method(test_input)"))
if BENCHMARK_ON:
print(f'{description} Benchmark: ', timeit.Timer(
f'for i in range({NUMBER_OF_RUNS}): {method(test_input)}', 'gc.enable()').timeit())
if method(test_input):
print(f'{GREEN_APPLE} {description}: "{test_input}" is a strong password.')
else:
print(f'{RED_APPLE} {description}: "{test_input}" is not a strong password.')
Output
🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎
re.match Benchmark: 1.8437564770000001
🍏 re.match: "abcAb1" is a strong password.
re.match Benchmark: 1.9900512190000006
🍏 re.match: "abcAb1abcAb1abcAb100" is a strong password.
re.match Benchmark: 1.782858269
🍎 re.match: "abcAb1abcAb1abcAb10111" is not a strong password.
re.match Benchmark: 1.8016775740000002
🍎 re.match: "aaaAb1abcAb1abcAb100" is not a strong password.
🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎
re.search Benchmark: 1.8374795240000008
🍏 re.search: "abcAb1" is a strong password.
re.search Benchmark: 1.8352807049999988
🍏 re.search: "abcAb1abcAb1abcAb100" is a strong password.
re.search Benchmark: 1.8023251919999996
🍎 re.search: "abcAb1abcAb1abcAb10111" is not a strong password.
re.search Benchmark: 1.9213070860000006
🍎 re.search: "aaaAb1abcAb1abcAb100" is not a strong password.
🍏🍎🍏🍎🍏🍎🍏🍎🍏🍎
re.findall Benchmark: 1.7806425130000019
🍏 re.findall: "abcAb1" is a strong password.
re.findall Benchmark: 1.836686480000001
🍏 re.findall: "abcAb1abcAb1abcAb100" is a strong password.
re.findall Benchmark: 1.8053996060000017
🍎 re.findall: "abcAb1abcAb1abcAb10111" is not a strong password.
re.findall Benchmark: 1.8203372360000003
🍎 re.findall: "aaaAb1abcAb1abcAb100" is not a strong password.
If you wish to simplify/modify/explore the expression, it's been explained on the top right panel of regex101.com. If you'd like, you can also watch in this link, how it would match against some sample inputs.
RegEx Circuit
jex.im visualizes regular expressions: