Skip to content

Instantly share code, notes, and snippets.

@heathermiller
Last active June 8, 2020 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heathermiller/562b05f77b54479e9228cc30f272edd9 to your computer and use it in GitHub Desktop.
Save heathermiller/562b05f77b54479e9228cc30f272edd9 to your computer and use it in GitHub Desktop.
Phone number cleanup in Unison

Clean up user-entered phone numbers so that they can be sent SMS messages.

The North American Numbering Plan (NANP) is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. All NANP-countries share the same international country code: 1.

NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as area code, followed by a seven-digit local number. The first three digits of the local number represent the exchange code, followed by the unique four-digit number which is the subscriber number.

The format is usually represented as

(NXX)-NXX-XXXX

where N is any digit from 2 through 9 and X is any digit from 0 through 9.

Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code (1) if present.

For example, the inputs

  • +1 (613)-995-0253
  • 613-995-0253
  • 1 613 995 0253
  • 613.995.0253

should all produce the output

6139950253

Note: As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code.

removePunc : Text -> Text -> Text
removePunc punc xs =
Text.fromCharList(List.foldl (acc x -> (if Search.elem x (Text.toCharList punc) then acc else acc :+ x )) [] (Text.toCharList xs))
number : Text -> Optional Text
number input =
xs = toCharList (removePunc "$@:!+.()-\s" input)
match xs with [] -> None
?1 +: rest -> number (Text.fromCharList rest)
?0 +: _ -> None
[_,_,_,?0] ++ rest -> None
[_,_,_,?1] ++ rest -> None
ys -> if ((size ys == 7) || (size ys == 10)) then Some (Text.fromCharList xs) else None
test> number.tests.ex1 =
check ( number "(223) 456-7890" == Some "2234567890")
test> number.tests.ex2 =
check ( number "223.456.7890" == Some "2234567890")
-- invalid when 9 digits
test> number.tests.ex3 =
check ( number "123456789" == None)
-- invalid when 11 digits does not start with a 1
test> number.tests.ex4 =
check ( number "22234567890" == None)
-- valid when 11 digits and starting with 1 even with punctuation
test> number.tests.ex5 =
check ( number "12234567890" == Some "2234567890")
test> number.tests.ex6 =
check ( number "+1 (223) 456-7890" == Some "2234567890")
-- invalid when more than 11 digits
test> number.tests.ex7 =
check ( number "321234567890" == None)
-- invalid if area code starts with 0 on valid 11-digit number
test> number.tests.ex8 =
check ( number "1 (023) 456-7890" == None)
-- invalid if area code starts with 1 on valid 11-digit number
test> number.tests.ex9 =
check ( number "1 (123) 456-7890" == None)
-- invalid if exchange code starts with 0 on valid 11-digit number
test> number.tests.ex10 =
check ( number "1 (223) 056-7890" == None)
-- invalid if exchange code starts with 1 on valid 11-digit number
test> number.tests.ex11 =
check ( number "1 (223) 156-7890" == None)
-- invalid with letters
test> number.tests.ex12 =
check ( number "123-abc-7890" == None)
-- invalid with punctuation
test> number.tests.ex13 =
check ( number "123-@:!-7890" == None)
-- invalid if area code starts with 0
test> number.tests.ex14 =
check ( number "(023) 456-7890" == None)
-- invalid if area code starts with 1
test> number.tests.ex15 =
check ( number "(123) 456-7890" == None)
-- invalid if exchange code starts with 0
test> number.tests.ex16 =
check ( number "(223) 056-7890" == None)
-- invalid if exchange code starts with 1
test> number.tests.ex17 =
check ( number "(223) 156-7890" == None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment