I have to make an assignment for my course computational thinking, but when I give this valid credit card number as input it keeps saying that the number is invalid, does anyone know why??
def ask_user():
string = (str(input("Please input your credit card number")))
numbers = list(map(int, string.split()))
if card_length(numbers):
validation(numbers)
else:
print("The credit card number you entered is invalid")
"""
This function takes the credit card number as a parameter and checks the length of the credit card number
to see if it is valid or not.
"""
def card_length(numbers):
for i in numbers:
if 13 <= i <= 16:
if numbers[0] == 4 or numbers[0] == 5 or numbers[0] == 6 or (numbers[0] == 3 and numbers[1] == 7):
return True
else:
return False
"""
This method takes the list of numbers and tells the user if it is a valid combination with a print statement
"""
def validation(numbers):
odd_results = odd_digits(numbers)
even_results = even_digits(numbers)
sum_of_results = odd_results + even_results
if sum_of_results % 10 == 0:
print("This credit card number is valid")
else:
print("This credit card number is invalid")
"""
This function takes the credit card number as a string list parameter and adds all
of the even digits in it.
"""
def even_digits(numbers):
length = len(numbers)
sumEven = 0
for i in range(length - 2, -1, -2):
num = eval(numbers[i])
num = num * 2
if num > 9:
strNum = str(num)
num = eval(strNum[0] + strNum[1])
sumEven += num
return sumEven
"""
This function takes the credit card number as a string list parameter and adds all
of the odd digits in it.
"""
def odd_digits(numbers):
length = len(numbers)
sumOdd = 0
for i in range(length - 1, -1, -2):
numbers += sumOdd
return sumOdd
"""
This is the main function that defines our first function called ask_user
"""
def main():
ask_user()
if __name__ == '__main__':
main()
The split() method returns a list of strings after breaking the given string by the specified separator.
Syntax : str.split(separator, maxsplit)
separator : This is a delimiter. The string splits at this specified separator. If is not provided then any white space is a separator.
maxsplit : It is a number, which tells us to split the string into maximum of provided number of times. If it is not provided then there is no limit.
Since you are taking the credit card number as a string without any spaces between the numbers, on splitting the credit card number you will get a list which contains the entire credit card number as a single element of the list(numbers). Therefore, the length of the numbers list will always be one and the card length function will always return False. I suggest you do something like:
string = (str(input("Please input your credit card number")))
numbers = list(map(int, list(string)))
Moving on, let me explain how the Luhn algorithm works:
The last digit in the number is taken as checksum. Alternate numbers starting from the number
next(on the left) to the checksum digit are doubled. If the number becomes a double digit on doubling
then the individual digits are added: 14 --> 1+4 = 5 (or) we could also subtract 9 from the digit
which would give us the same answer: 14-9 =5. All the digits(excluding the checksum digit) are now
added. The sum of these digits is multiplied by 9 and the mod 10 of the number is taken. If the
result of the mod 10 of the number is equal to the checksum digit, then the number is valid.
This is one of the ways in which you could write the code for the algorithm:
card_number = list(map(int, list(input('Enter the credit card number : '))))
card_number.reverse()
checksum = card_number.pop(0)
for i in range(len(card_number)):
if i % 2 == 0:
x = card_number[i] * 2
if len(str(x)) == 2:
x -= 9
card_number[i] = x
total = sum(card_number) * 9
total %= 10
if total == checksum:
print('It is a valid number')
else:
print('It is not a valid number')
Related
Trying to implement a program in Python that can check if the input is a valid credit card and display the credit card type(VISA/MASTERCARD/AMEX). For 2 values it's displaying incorrectly and for 2 days I have no ideas how to fix it ?
Output received:( last 2 are incorect 4111111111111113 and 4222222222223) I guess is something related with the check_last_digit function ....
identifies 378282246310005 as AMEX
:) identifies 371449635398431 as AMEX
:) identifies 5555555555554444 as MASTERCARD
:) identifies 5105105105105100 as MASTERCARD
:) identifies 4111111111111111 as VISA
:) identifies 4012888888881881 as VISA
:) identifies 4222222222222 as VISA
:) identifies 1234567890 as INVALID
:) identifies 369421438430814 as INVALID
:) identifies 4062901840 as INVALID
:) identifies 5673598276138003 as INVALID
:( **identifies 4111111111111113 as INVALID**
**expected "INVALID\n", not "VISA\n\n"**
:( **identifies 4222222222223 as INVALID**
**expected "INVALID\n", not "VISA\n\n**
My Code:
#function to find out the sum of every other numbers from the input card
def odd_sum(num):
num = list(str(num))
my_list_digits = [int(item) * 2 for item in num][::2]
total_odd = 0
for number in my_list_digits:
if number > 9:
first_digit = number // 10
second_digit = number % 10
total_odd += first_digit + second_digit
else:
total_odd += number
return total_odd
# function to find out the sum of the other remaining numbers
def even_sum(num):
num = list(str(num))
del num[::2]
my_list_digits1 = [int(item) for item in num]
total_even = 0
for item in my_list_digits1:
total_even += item
return total_even
# function to check the lenght of the input card
def check_length(num):
num = str(num)
num_length = len(num)
if 13 <= num_length <= 16:
return True
else:
print("INVALID")
# function to check the last digit of the sum ( even and odd)
def check_last_digit(num):
odd = odd_sum(num)
even = even_sum(num)
if (odd + even) % 10 == 0:
return True
else:
return False
# function to determine the type of card that was provided
def card_type(card_num):
card_num = str(card_num)
AMEX = ["34", "37"]
MASTERCARD = ["51", "52", "53", "54", "55"]
VISA = ["4"]
if (card_num[0:2]) in AMEX:
print("AMEX")
elif (card_num[0:2]) in MASTERCARD:
print("MASTERCARD")
elif (card_num[0]) == VISA[0]:
print("VISA\n")
else:
print("INVALID")
# main program to run all the above created functions
def main():
#get input from user
card_num = int(input("CARD: "))
#check if the bellow 2 functions are True and if so, run the card type function so we can see what type of card was usde(visa, mastercard,amex)
if check_length(card_num):
card_type(card_num)
else:
if check_last_digit(card_num):
card_type(card_num)
main()
It looks like in your main function
#check if the bellow 2 functions are True and if so, run the card type function so we can see what type of card was usde(visa, mastercard,amex)
if check_length(card_num):
card_type(card_num)
else:
if check_last_digit(card_num):
card_type(card_num)
is supposed to check that both check_length and check_last_digit are passed. However, in your code, if check_length returns True, then the second check is not ran. You need to change your code to make sure that both test are run:
def main():
#get input from user
card_num = int(input("CARD: "))
#check if the bellow 2 functions are True and if so, run the card type function so we can see what type of card was usde(visa, mastercard,amex)
if check_length(card_num) and check_last_digit(card_num):
card_type(card_num)
else:
print("INVALID")
Edit:
There are two other errors in your implementation of the Luhn algorithm.
The odd_sum function is supposed to sum every other digit, starting from the right-most one, and skipping one, but your implementation sums the wrong digits if the number of digits of the input number is odd. To correct for that, you should, for instance, reverse the list first:
l = [int(item) * 2 for item in num[::-1]]
then, remove the first digit (the rightmost one)
l = l[1:]
and finally, take every other digit:
my_list_digits = l[::2]
Then, there's a similar error in even_sum, you should also consider reversing the list, to make sure to consider the correct digits:
my_list_digits1 = [int(item) for item in num[::-1]]
return sum(my_list_digits1)
Lastly, as Jakob mentioned, you should return False instead of "INVALID" in your check_length function.
As a refactoring tip, if you see yourself writing
if condition:
return True
else:
return False
then you can refactor that in the cleaner:
return condition
So for instance:
def check_last_digit(num):
odd = odd_sum(num)
even = even_sum(num)
return (odd + even) % 10 == 0:
How can I pick one of the digits from an Integer like: 97723
and choose (for example) the number 2 from that number and check if its an odd or an even number?
Also, can I print only the odd numbers from an Integer directly? (Is there any default function for that already?)
Thanks in advance
2 is the 4th digit.
You can get the digits of a number using this construct.
digits = [int(_) for _ in str(97723)]
This expression will be true if the 4th digit is even.
digits[3] % 2 == 0
# choose a digit (by index)
integer = 97723
digit_3 = str(integer)[3]
print(digit_3)
# check if even:
if int(digit_3) % 2 == 0:
print(digit_3, "is even")
# get all odd numbers directly
odd_digits = [digit for digit in str(integer) if int(digit) % 2 == 1]
print(odd_digits)
even = lambda integer: int("".join([num for num in str(integer) if int(num) % 2 == 0]))
or
def even(integer):
result = ""
integer = str(integer)
for num in integer:
if int(num) % 2 == 0:
result += num
result = int(result)
return(result)
If you want to "parse" a number the easiest way to do this is to convert it to string. You can convert an int to string like this s = string(500). Then use string index to get character that you want. For example if you want first character (number) then use this string_name[0], for second character (number) use string_name[1] . To get length of your string (number) use len(string). And to check if number is odd or even mod it with 2.
# Converting int to string
int_to_sting = str(97723)
# Getting number of characters in your string (in this case number)
n_of_numbers = len(int_to_sting)
# Example usage of string index
print("First number in your number is: ",int_to_sting[0])
print("Second number in your number is: ",int_to_sting[1])
# We need to check for every number, and since the first number is int_to_sting[0] and len(int_to_sting) returns actual length of string we need to reduce it by 1
for i in range(n_of_numbers-1):
if int_to_sting[i]%2==0:
print(int_to_sting[i]," is even")
else:
print(int_to_sting[i]," is odd")
I'm making a program that validates a credit card, by multiplying every other number in the card number by 2; after i'll add the digits multiplied by 2 to the ones not multiplied by 2. All of the double digit numbers are added by the sum of their digits, so 14 becomes 1+4. I have a photo below that explains it all. I'm making a python program that does all of the steps. I've done some code below for it, but I have no idea what to do next? Please help, and it would be greatly appreciated. The code I have returns an error anyway.
class Validator():
def __init__(self):
count = 1
self.card_li = []
while count <= 16:
try:
self.card = int(input("Enter number "+str(count)+" of your card number: "))
self.card_li.append(self.card)
#print(self.card_li)
if len(str(self.card)) > 1:
print("Only enter one number!")
count -= 1
except ValueError:
count -= 1
count += 1
self.validate()
def validate(self):
self.card_li.reverse()
#print(self.card_li)
count = 16
while count >= 16:
self.card_li[count] = self.card_li[count] * 2
count += 2
Validator()
To perform that sum:
>>> s = '4417123456789113'
>>> sum(int(c) for c in ''.join(str(int(x)*(2-i%2)) for i, x in enumerate(s)))
70
How it works
The code consists of two parts. The first part creates a string with every other number doubled:
>>> ''.join(str(int(x)*(2-i%2)) for i, x in enumerate(s))
'8427226410614818123'
For each character x in string s, this converts the character to integer, int(x) and multiplies it by either 1 or 2 depending on whether the index, i, is even or odd: (2-i%2). The resulting product is converted back to a string: str(int(x)*(2-i%2)). All the strings are then joined together.
The second part sums each digit in the string:
>>> sum(int(c) for c in '8427226410614818123')
70
You need to increment the count inside the while() loop. Also, append the user input to your card_li list after you have the if.. check. Your init method should look like:
def __init__(self):
count = 1
self.card_li = []
while count <= 16:
try:
self.card = int(input("Enter number "+str(count)+" of your card number: "))
if len(str(self.card)) > 1:
print("Only enter one number!")
self.card_li.append(self.card)
count += 1
except ValueError:
pass
self.validate()
As for your validate method, it doesn't seem complete even according to the logic you have written.
I am working on this project in which I have to check if a credit card number is valid or not. In this case I only need an 8 digit credit card(I know that's not reality). Here is the question
The last digit of a credit card number is the check digit, which protects against transcription errors such as an error in a single digit or switching two digits. The following method is used to verify actual credit card numbers but, for simplicity, we will describe it for numbers with 8 digits instead of 16:
• Starting from the rightmost digit, form the sum of every other
digit. For example, if the credit card number is 4358 9795, then you
form the sum 5 + 7 + 8 + 3 = 23.
• Double each of the digits that were not included in the preceding
step. Add all digits of the resulting numbers. For example, with the
number given above, doubling the digits, starting with the
next-to-last one, yields 18 18 10 8. Adding all digits in these values
yields 1 + 8 + 1 + 8 + 1 + 0 + 8 = 27.
• Add the sums of the two preceding steps. If the last digit of the
result is 0, the number is valid. In our case, 23 + 27 = 50, so the
number is valid.
Write a program that implements this algorithm. The user should supply an 8-digit number, and you should print out whether the number is valid or not. If it is not valid, you should print the value of the check digit that would make it valid.
I have to use loops to do the sum. However, I do not know how to use loops for that.
Here's my code
# Credit Card Number Check. The last digit of a credit card number is the check digit,
# which protects against transcription errors such as an error in a single digit or
# switching two digits. The following method is used to verify actual credit card
# numbers but, for simplicity, we will describe it for numbers with 8 digits instead
# of 16:
# Starting from the rightmost digit, form the sum of every other digit. For
# example, if the credit card number is 43589795, then you form the sum
# 5 + 7 + 8 + 3 = 23.
# Double each of the digits that were not included in the preceding step. Add # all
# digits of the resulting numbers. For example, with the number given above,
# doubling the digits, starting with the next-to-last one, yields 18 18 10 8. Adding
# all digits in these values yields 1 + 8 + 1 + 8 + 1 + 0 + 8 = 27.
# Add the sums of the two preceding steps. If the last digit of the result is 0, the
# number is valid. In our case, 23 + 27 = 50, so the number is valid.
# Write a program that implements this algorithm. The user should supply an 8-digit
# number, and you should print out whether the number is valid or not. If it is not
# valid, you should print out the value of the check digit that would make the number
# valid.
card_number = int(input("8-digit credit card number: "))
rights = 0
for i in card_number[1::2]:
rights += int(i)
lefts = 0
for i in card_number[::2]:
lefts += int(i)*2%10+int(i)*2/10
print card_number, (rights +lefts)/10
if remaining == 0:
print("Card number is valid")
else:
print("Card number is invalid")
if digit_7 - remaining < 0:
checkDigit = int(digit_7 + (10 - remaining))
print("Check digit should have been:", checkDigit)
else:
checkDigit = int(digit_7 - remaining)
print("Check digit should have been:", checkDigit)
If I understand correctly, you are looking for something like this:
cards = ["43589795"]
for card_number in cards:
rights = sum(map(int, card_number[1::2]))
lefts = sum(map(lambda x: int(x)*2%10+int(x)*2/10, card_number[::2])) # sum of doubled values
print card_number, (rights +lefts)/10
Same solution without map and lambda magic:
rights = 0
for i in card_number[1::2]:
rights += int(i)
lefts = 0
for i in card_number[::2]:
lefts += int(i)*2%10+int(i)*2/10
print card_number, (rights +lefts)/10
And full answer on your question:
card_number = str(raw_input("8-digit credit card number: ")).replace(" ", "")
rights = 0
for i in card_number[1::2]:
rights += int(i)
lefts = 0
for i in card_number[::2]:
lefts += int(i)*2%10+int(i)*2/10
remaining = (rights +lefts)%10
digit_7 = int(card_number[-1]) # Last digit
if remaining == 0:
print("Card number is valid")
else:
print("Card number is invalid")
if digit_7 - remaining < 0:
checkDigit = int(digit_7 + (10 - remaining))
print("Check digit should have been:", checkDigit)
else:
checkDigit = int(digit_7 - remaining)
print("Check digit should have been:", checkDigit)
Here is another possible solution:
cc_number = input("8-digit credit card number: ").replace(" ", "")
total1 = 0
total2 = 0
for digit in cc_number[-1::-2]:
total1 += int(digit)
for digit in cc_number[-2::-2]:
total2 += sum(int(x) for x in str(int(digit)*2))
remainder = (total1 + total2) % 10
if remainder == 0:
print("Card is valid!")
else:
invalid_check_digit = int(cc_number[-1])
if invalid_check_digit - remainder < 0:
valid_check_digit = invalid_check_digit + (10 - remainder)
else:
valid_check_digit = invalid_check_digit - remainder
print("Card is invalid - the correct check digit is {}".format(valid_check_digit))
Giving you the following output:
8-digit credit card number: 4358 9795
Card is valid!
Or:
8-digit credit card number: 4358 9794
Card is invalid - the correct check digit is 5
Prune all spaces from the credit card number and try the following code:
import itertools
sum = 0
for multiplicand,didgit in zip(itertools.cycle([2,1]), str(CREDIT_CARD_NUMBER)):
result = multiplicand * int(didgit)
sum += result / 10
sum += result % 10
print "valid" if sum % 10 == 0 else "invalid"
The above code loops through the credit card number and computes both sums simultainously.
Here is a solution using numpy:
import numpy as np
d1=np.transpose(np.array(list('43589795'), dtype=np.uint8).reshape((4,2)))[0]*2
d2=np.transpose(np.array(list('43589795'), dtype=np.uint8).reshape((4,2)))[1]
if (np.sum(np.hstack([list(entry) for entry in d1.astype(str)]).astype(np.uint8))+np.sum(d2))%10==0:
return "Validated"
In the example case, we get 50 which is validated.
I am working in python 3 and I am making a program that will take in a 10 digit ISBN Number and applying a method to it to find the 11th number.
Here is my current code
ISBN=input('Please enter the 10 digit number: ')
while len(ISBN)!= 10:
print('Please make sure you have entered a number which is exactly 10 characters long.')
ISBN=int(input('Please enter the 10 digit number: '))
continue
else:
Digit1=int(ISBN[0])*11
Digit2=int(ISBN[1])*10
Digit3=int(ISBN[2])*9
Digit4=int(ISBN[3])*8
Digit5=int(ISBN[4])*7
Digit6=int(ISBN[5])*6
Digit7=int(ISBN[6])*5
Digit8=int(ISBN[7])*4
Digit9=int(ISBN[8])*3
Digit10=int(ISBN[9])*2
Sum=(Digit1+Digit2+Digit3+Digit4+Digit5+Digit6+Digit7+Digit8+Digit9+Digit10)
Mod=Sum%11
Digit11=11-Mod
if Digit11==10:
Digit11='X'
ISBNNumber=str(ISBN)+str(Digit11)
print('Your 11 digit ISBN Number is ' + ISBNNumber)
I want to create some kind of loop so that the number after "Digit" for the variable name increases starting from 1 (or zero if it makes life easier), the number in the square brackets increases starting from 0 and the multiplication number to decrease from 11 to 2.
Is there any way of doing this code in a more efficient way?
I think this should do what you want.
def get_isbn_number(isbn):
digits = [(11 - i) * num for i, num in enumerate(map(int, list(isbn)))]
digit_11 = 11 - (sum(digits) % 11)
if digit_11 == 10:
digit_11 = 'X'
digits.append(digit_11)
isbn_number = "".join(map(str, digits))
return isbn_number
EXAMPLE
>>> print(get_isbn_number('2345432681'))
22303640281810242428
>>> print(get_isbn_number('2345432680'))
2230364028181024240X
Explanation of second line:
digits = [(11 - i) * num for i, num in enumerate(map(int, list(isbn)))]
Could be written out like:
isbn_letters = list(isbn) # turn a string into a list of characters
isbn_numbers = map(int, isbn_letters) # run the function int() on each of the items in the list
digits = [] # empty list to hold the digits
for i, num in enumerate(isbn_numbers): # loop over the numbers - i is a 0 based counter you get for free when using enumerate
digits.append((11 - i) * num) # If you notice the pattern, if you subtract the counter value (starting at 0) from 11 then you get your desired multiplier
Terms you should look up to understand the one line version of the code:
map,
enumerate,
list conprehension
ISBN=int(input('Please enter the 10 digit number: ')) # Ensuring ISBN is an integer
while len(ISBN)!= 10:
print('Please make sure you have entered a number which is exactly 10 characters long.')
ISBN=int(input('Please enter the 10 digit number: '))
continue
else:
Sum = 0
for i in range(len(ISBN)):
Sum += ISBN[i]
Mod=Sum%11
Digit11=11-Mod
if Digit11==10:
Digit11='X'
ISBNNumber=str(ISBN)+str(Digit11)
print('Your 11 digit ISBN Number is ' + ISBNNumber)