iaianmcd iaianmcd - 2 months ago 15
Python Question

Credit card check exercise python

for a free online Python tutorial I need to:


to write a function which checks if a given credit card number is
valid. The function
check(S)
should take a string
S
as input. First,
if the string does not follow the format
"#### #### #### ####"
where
each
#
is a digit, then it should return
False
. Then, if the sum of
the digits is divisible by
10
(a "checksum" method), then the
procedure should return
True
, else it should return
False
. For
example, if
S
is the string
"9384 3495 3297 0123"
then although the
format is correct, the digit sum is
72
so you should return
False
.


The following shows what I have come up with. I think my logic is correct but don't quite understand why it is giving me the wrong value. Is there a structural issue in my code, or am I using a method incorrectly?

def check(S):
if len(S) != 19 and S[4] != '' and S[9] != '' and S[14] != '':
return False # checking if the format is correct

S = S.replace(" ",'') # Taking away spaces in the string
if not S.isdigit():
return False # checking that the string has only numbers

L = []
for i in S:
i = int(i) # Making a list out of the string and converting each character to an integer so that it the list can be summed
L.append(i)
if sum(L)//10 != 0: # checking to see if the sum of the list is divisible by 10
return False

Answer

You are not testing for spaces, only for empty strings, which you'll never find when using straight indices on a python string.

Moreover, you should return False if any of those 4 conditions is true, not if they are all true at the same time:

if len(S) != 19 or S[4] != ' ' or S[9] != ' ' or S[14] != ' ':
    return False

Next, you replace the spaces, but don't check the length again. What if I had given you 19 spaces:

S = S.replace(" ", '')
if len(S) != 16 or not S.isdigit():
    return False

Last, you want first collect all the digits, and check if there is a remainder:

L = map(int, S)  # makes S into a sequence of integers in one step
if sum(L) % 10 != 0:  # % calculates the remainder, which should be 0
    return False

and don't forget to return True if all those tests have passed:

return True

at the end.

Put that all together and you get:

>>> def check(S):
...     if len(S) != 19 or S[4] != ' ' or S[9] != ' ' or S[14] != ' ':
...         return False
...     S = S.replace(" ", '')
...     if len(S) != 16 or not S.isdigit():
...         return False
...     L = map(int, S)  # makes S into a sequence of integers in one step
...     if sum(L) % 10 != 0:  # % calculates the remainder, which should be 0
...         return False
...     return True
... 
>>> check('9384 3495 3297 0123')
False
>>> check('9384 3495 3297 0121')
True