'Social Security Number Check - Python

Writing a program that prompts the user to enter a social security number in the format ddd-dd-dddd where d is a digit. The program displays "Valid SSN" for a correct Social Security number or "Invalid SSN" if it's not correct. I nearly have it, just have one issue.

I'm not sure how to check if it's in the right format. I can enter for instance:

99-999-9999

and it'll say that it's valid. How do I work around this so that I only get "Valid SSN" if it's in the format ddd-dd-dddd?

Here's my code:

def checkSSN():
ssn = ""
while not ssn:  
    ssn = str(input("Enter a Social Security Number in the format ddd-dd-dddd: "))
    ssn = ssn.replace("-", "") 
    if len(ssn) != 9: # checks the number of digits
        print("Invalid SSN")
    else:
        print("Valid SSN")


Solution 1:[1]

How about this:

SSN = raw_input("enter SSN (ddd-dd-dddd):")
chunks = SSN.split('-')
valid=False
if len(chunks) ==3: 
   if len(chunks[0])==3 and len(chunks[1])==2 and len(chunks[2])==4:
       valid=True
print valid

Solution 2:[2]

You can use re to match the pattern:

In [112]: import re

In [113]: ptn=re.compile(r'^\d\d\d-\d\d-\d\d\d\d$')

Or r'^\d{3}-\d{2}-\d{4}$' to make the pattern much readable as @Blender mentioned.

In [114]: bool(re.match(ptn, '999-99-1234'))
Out[114]: True

In [115]: bool(re.match(ptn, '99-999-1234'))
Out[115]: False

From the docs:

'^'
(Caret.) Matches the start of the string, and in MULTILINE mode also matches immediately after each newline.
'$'
Matches the end of the string or just before the newline at the end of the string

\d
When the UNICODE flag is not specified, matches any decimal digit; this is equivalent to the set [0-9].

Solution 3:[3]

Without using regular expressions I'd suggest a straightforward way:

def checkSSN(ssn):
    ssn = ssn.split("-")
    if map(len, ssn) != [3,2,4]:
        return False
    elif any(not x.isdigit() for x in ssn):
        return False
    return True

Two-liner with all things collapsed together:

def checkSSN(ssn):
    ssn = ssn.split("-")
    return map(len,ssn) == [3,2,4] and all(x.isdigit() for x in ssn)

Note: if you are using Python 3, you'll need to convert map to list: list(map(...))

Solution 4:[4]

I'd like to add an answer using regex and python3

import re

# Tests
data = [
    "enter SSN (989-45-8524):",
    "456748965", 
    "e43-45-7845", 
    "***-**-4598", 
    "4-98-4589", 
    "Social security Number is: [783-65-7485]", 
    458859635, 
    " Some text"
]

for ssn in data:
    # Grab only digit and check length of string. 
    # This line is the magik
    _ssn = "".join(re.findall(r"[\d]+", str(ssn)))

    if len(_ssn) == 9:
        print(ssn, f"{_ssn} is valid!")


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Marx
Solution 2
Solution 3
Solution 4 Wolfgang Leon