I'm practicing some Python and I'm having trouble understanding why this code won't take - function takes a string and if it's at least 10 characters in length, has at least 1 digit, 1 lowercase, and 1 uppercase letter, it should return True. Also, there's gotta be a more succinct way to write this than I did with all these nested conditionals. Thanks all!
import string
alphalower = string.ascii_lowercase
alphaupper = string.ascii_uppercase
digs = string.digits
def checkio(data):
if len(data) >= 10:
if data.count(digs) >= 1:
if data.count(alphaupper) >= 1:
if data.count(alphalower) >= 1:
return True
else:
return False
It must contain at least one lowercase letter, at least one uppercase letter, and at least one numeric character. It must not contain three repeating characters in a row like … aaa…, …
import time complete = False user = [["username","password"],["username2","password2"]] while not complete: username = input("What is the username?") password = input("What is the password?") for n in len(user): if username == user[n][0]: print("Good!") if password == user[n][1]: print("User has been identified, ...
valid_username(username) # if it isn't valid we should tell them why if not(result): print (reason) # otherwise the username is good - ask them for a password # get a password from the user password = input("Password: ") # determine if the password is valid pwresult, pwreason = uservalidation.
Conditions for a valid password are: Should have at least one number. Should have at least one uppercase and one lowercase character. Should have at least one special symbol. Should be between 6 to 20 characters long.
The following should work, and removes the unnecessary imports :
def checkio(data):
return len(data) >= 10 and any(char.isdigit() for char in data) and any(char.islower() for char in data) and any(char.isupper() for char in data)
You can iterate over strings by default, and each string has the isdigit, islower, etc... methods that you can use. The any()
method returns True if any of the values returned by an iterable passed to it is true, and the something(value) for value in iterable
syntax creates a generator expression, which iterates over each character of the string and checks whether it's a digit/lowercase/uppercase character.
Based on this answer.
Benchmark time, with my horrible benchmark code (but it seems to do the job) :
from time import time
import re
data = "ULFFunH8ni" # the password
def benchmark(method): # benchmark method, loops 1000000 times and prints how much it took
start = time()
for _ in range(1000000): method(data)
print(time() - start)
def checkio_kasra(data): # Kasra's answer
return len(data) >= 10 and all([any(i.isdigit() for i in data),any(i.islower() for i in data),any(i.isupper() for i in data)])
def checkio_andreysabitov(data): # Andrey Sabitov's regex-based answer
if len(data) < 10:
return False
digital = re.compile('[0-9]+')
capital = re.compile('[A-Z]+')
lower = re.compile('[a-z]+')
return (digital.search(data) is not None) and (capital.search(data) is not None) and (lower.search(data) is not None)
def checkio_andredaniel(data): # My answer
return len(data) >= 10 and any(char.isdigit() for char in data) and any(char.islower() for char in data) and any(char.isupper() for char in data)
def checkio_shashank_bitmask(data):
if len(data) < 10: return False
lud_bitmask = 0
for ch in data:
if ch.islower():
lud_bitmask |= 4
if lud_bitmask == 7: return True
elif ch.isupper():
lud_bitmask |= 2
if lud_bitmask == 7: return True
elif ch.isdigit():
lud_bitmask |= 1
if lud_bitmask == 7: return True
return False
def checkio_shashank_pure_regex(data):
return bool(re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z]).{10}', data))
def checkio_shashank_impure_regex(data):
return len(data) >= 10 and re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z])', data)
benchmark(checkio_kasra)
benchmark(checkio_andreysabitov)
benchmark(checkio_andredaniel)
benchmark(checkio_shashank_bitmask)
benchmark(checkio_shashank_pure_regex)
benchmark(checkio_shashank_impure_regex)
The results, on my low-end tablet running Windows 7 and Python 3.4.x (ran it two times to be sure) :
$ python pass.py
6.333611011505127 # Shashank
9.625216960906982 # Kasra
11.450419902801514 # Andrey Sabitov
8.36161494255066 # Me
However, given a semi-incorrect input of 1XYZXYZXYZ
(length and digits are good, but all uppercase), some solutions fail to stop early :
7.456813097000122 # Shashank
9.328815937042236 # Kasra
11.169620037078857 # Andrey Sabitov
6.349210977554321 # Me
Note that these benchmarks don't take into account eventual edits. I suggest you run the benchmark on your own machine using the latest answers. Feel free to update this post with new results.
import re
def checkio(data):
if len(data) < 10:
return False
digital = re.compile('[0-9]+')
capital = re.compile('[A-Z]+')
lower = re.compile('[a-z]+')
return (digital.search(data) is not None) and (capital.search(data) is not None) and (lower.search(data) is not None)
You can use 3 generator expression with any
function within all
:
def checkio(data):
return len(data) >= 10 and all([any(i.isdigit() for i in data),any(i.islower() for i in data),any(i.isupper() for i in data)])
Demo :
>>> checkio('1&*^&^%%gA')
True
>>> checkio('1&*^&^%%gf')
False
One unique way of doing it would be to use a bitmask:
def checkio_shashank_bitmask(data):
if len(data) < 10: return False
lud_bitmask = 0
for ch in data:
if ch.islower():
lud_bitmask |= 4
if lud_bitmask == 7: return True
elif ch.isupper():
lud_bitmask |= 2
if lud_bitmask == 7: return True
elif ch.isdigit():
lud_bitmask |= 1
if lud_bitmask == 7: return True
return False
print(checkio('5Hortpass')) # False
print(checkio('dumbpa55w0rd')) # False
print(checkio('DumbPassword')) # False
print(checkio('DumbPassword2015')) # True
This scales well for large inputs and stops as early as it can.
Here is what I think to be an optimized regex solution with non-greedy positive lookaheads that stops as soon as possible:
import re
def checkio_shashank_pure_regex(data):
return bool(re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z]).{10}', data))
However, I am not a regex expert, so if you have any optimization ideas, let me know.
From some further testing, I've determined that this is a bit faster and is probably the fastest solution so far for both correct and incorrect inputs at least with a highly optimized regex module:
def checkio_shashank_impure_regex(data):
return len(data) >= 10 and re.match(r'(?=.*?[0-9])(?=.*?[A-Z])(?=.*?[a-z])', data)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With