I have a credit card company ABC which issues credit card numbers based on the following rules:
1. The number must contain exactly 16 digits
2. The input string must not have any other character apart from hyphen as separator
3. The input may contain four number groups separated by a hyphen e.g 5122-2368-7954- 3214
4. The input must not have 4 or more repeated numbers
5. The input must start with either 4 , 5 or 6
I wrote python code to get an input from a user and process it according to the conditions above, if string satisfies all the requirements above then the code should output "Valid" else it should print "Invalid"
Input Format
My first input line takes the number of input strings the program is to take from the user. For example if user wants to pass string input four times, he would pass 4 as an input for this first line.
##take input for number of test cases user wants to run
T=int(input())
The next T lines contain the credit card number input needed for the program to process. My code has been broken down into how I tried to tackle each step declared above, if string fails a single condition then we ignore the body of our loop and skip to the next iteration to process the next user string.
for r in range(T):
##read current credit card string from user
credit=input()
##step 1
##check if the string has a minumum of 16 digits
digit_count=0
for el in credit:
if(el.isdigit()):
digit_count =1
##check and skip to next iteration if false after Invalid output
if(digit_count!=16):
print("Invalid")
continue
##If this string does have a hyphen then we have to make sure the other
if('-' in credit):
##check and make sure that te hyphen indices do not have a non hyphen character
if(credit[4]!='-' or credit[9]!='-' or credit[14]!='-'):
##print invalid and go to the next iteration
print("Invalid")
continue
##also make sure the hyphen split the input into a group of four numbers
if(len(credit.split("-")!=4):#this operation should create an array of four members
print("Invalid")
continue
##continuing to processs input not having 4 or more repeated characters
##remove the hyphens first from the input
pure_nos=credit.replace("-","")
##compare length of set of pure_nos against the length of pure_nos
if(len(pure_nos)-len(set(pure_nos))>=4):
print("Invalid")
continue
##make sure the first character is either a 4 , 5 or 6
if(credit[0]!='4' or credit[0]!='5' or credit[0]!='6'):
print("Invalid")
continue
##if a string passes all the above then it must be valid
print("Valid")
The input strings I am using
Foreach iteration i pass the values below as input in that order downwards
6
4123456789123456
5123-4567-8912-3456
61234-567-8912-3456
4123356789123456
5133-3367-8912-3456
5123 - 3567 - 8912 - 3456
Output
My code returns Invalid
for all test cases , please help me correct this.
CodePudding user response:
I would take a slighly different approach. First refactor your check into a function: Now you can return if the credit is valid or not and don't have to work with many continue
s.
First I would process the numbers in the credit card:
numbers = ""
for number in credit:
# ignore spaces
if number == " ":
continue
# we found a "-".
# Now check if the length of numbers is divisible by 4
if number == "-" and len(numbers) % 4 == 0:
continue
# not a number
# (Note that "-" and " " are also valid because
# of the continue)
if not number.isdigit():
return False
# add the number to all numbers
numbers = number
Now you can check their length:
if len(numbers) != 16:
return False
After that check the repetition: For each number in the credit card, check if any of the following 3 numbers is not equal
# iterate over all numbers but not the last three
# because if a repetition would start there
# it would be to small
for i in range(len(numbers) - 3):
repetition = True
# check each of the next three characters
for j in range(1, 4):
# we have found a different number,
# so there is no repetition here
if numbers[i] != numbers[i j]:
repetition = False
if repetition:
return False
Last check the first character:
if credit[0] not in "456":
return False
Full code of check function:
def check_credit(credit):
# process numbers
numbers = ""
for number in credit:
if number == " ":
continue
if number == "-" and len(numbers) % 4 == 0:
continue
if not number.isdigit():
return False
numbers = number
# check length
if len(numbers) != 16:
return False
# check for repetition
for i in range(len(numbers) - 3):
repetition = True
for j in range(1, 4):
if numbers[i] != numbers[i j]:
repetition = False
if repetition:
return False
# check first character
if credit[0] not in "456":
return False
return True
Additionally I added a function to test the check function with your testcases (assert
throws an exception if the value behind it is not truthy):
def test():
assert check_credit("4123456789123456")
assert check_credit("5123-4567-8912-3456")
# invalid: group of five
assert not check_credit("61234-567-8912-3456")
assert check_credit("4123356789123456")
# invalid: repetition
assert not check_credit("5133-3367-8912-3456")
assert check_credit("5123 - 3567 - 8912 - 3456")
And last I added a function to get the user input as you did in your question:
def user_input():
# note that variables in python should be lowercase
t = int(input())
for r in range(t):
credit = input()
if check_credit(credit):
print("Valid")
else:
print("Invalid")