iaianmcd - 1 year ago 58

Python Question

for a free online Python tutorial I need to:

to write a function which checks if a given credit card number is

valid. The functionshould take a string`check(S)`

as input. First,`S`

if the string does not follow the formatwhere`"#### #### #### ####"`

eachis a digit, then it should return`#`

. Then, if the sum of`False`

the digits is divisible by(a "checksum" method), then the`10`

procedure should return, else it should return`True`

. For`False`

example, ifis the string`S`

then although the`"9384 3495 3297 0123"`

format is correct, the digit sum isso you should return`72`

.`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 Source

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
```