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.
Execute the tests with:
$ elixir phone_number_test.exs
In the test suites, all but the first test have been skipped.
Once you get a test passing, you can unskip the next one by
commenting out the relevant @tag :pending
with a #
symbol.
For example:
# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
Or, you can enable all the tests by commenting out the
ExUnit.configure
line in the test suite.
# ExUnit.configure exclude: :pending, trace: true
For more detailed information about the Elixir track, please see the help page.
Event Manager by JumpstartLab http://tutorials.jumpstartlab.com/projects/eventmanager.html
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
Code.load_file("phone_number.exs", __DIR__)
end
ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)
defmodule PhoneTest do
use ExUnit.Case
test "cleans number" do
assert Phone.number("(212) 555-0100") == "2125550100"
end
@tag :pending
test "cleans number with dots" do
assert Phone.number("212.555.0100") == "2125550100"
end
@tag :pending
test "valid when 11 digits and first is 1" do
assert Phone.number("12125550100") == "2125550100"
end
@tag :pending
test "valid when 11 digits and some decorations" do
assert Phone.number("+1 (212) 555-0100") == "2125550100"
end
@tag :pending
test "invalid when country calling code is not 1" do
assert Phone.number("22125550100") == "0000000000"
end
@tag :pending
test "invalid when 9 digits" do
assert Phone.number("212555010") == "0000000000"
end
@tag :pending
test "invalid when proper number of digits but letters mixed in" do
assert Phone.number("2a1a2a5a5a5a0a1a0a0a") == "0000000000"
end
@tag :pending
test "invalid with correct number of characters but some are letters" do
assert Phone.number("2a1a2a5a5a") == "0000000000"
end
@tag :pending
test "invalid when area code begins with 1" do
assert Phone.number("1125550100") == "0000000000"
end
@tag :pending
test "invalid when area code begins with 0" do
assert Phone.number("0125550100") == "0000000000"
end
@tag :pending
test "invalid when exchange code begins with 1" do
assert Phone.number("2121550100") == "0000000000"
end
@tag :pending
test "invalid when exchange code begins with 0" do
assert Phone.number("2120550100") == "0000000000"
end
@tag :pending
test "area code" do
assert Phone.area_code("2125550100") == "212"
end
@tag :pending
test "area code with full US phone number" do
assert Phone.area_code("12125550100") == "212"
end
@tag :pending
test "invalid area code" do
assert Phone.area_code("(100) 555-1234") == "000"
end
@tag :pending
test "no area code" do
assert Phone.area_code("867.5309") == "000"
end
@tag :pending
test "pretty print" do
assert Phone.pretty("2125550100") == "(212) 555-0100"
end
@tag :pending
test "pretty print with full US phone number" do
assert Phone.pretty("+1 (303) 555-1212") == "(303) 555-1212"
end
@tag :pending
test "pretty print invalid US phone number" do
assert Phone.pretty("212-155-0100") == "(000) 000-0000"
end
@tag :pending
test "pretty print invalid, short US phone number" do
assert Phone.pretty("867.5309") == "(000) 000-0000"
end
end
defmodule Phone do
@invalid "0000000000"
@doc """
Remove formatting from a phone number.
Returns "0000000000" if phone number is not valid
(10 digits or "1" followed by 10 digits)
## Examples
iex> Phone.number("123-456-7890")
"1234567890"
iex> Phone.number("+1 (303) 555-1212")
"3035551212"
iex> Phone.number("867.5309")
"0000000000"
"""
@spec number(String.t) :: String.t
def number(raw) do
trim = String.replace raw, ~r/[^[:alnum:]]/, ""
trimlen = String.length trim
cond do
trimlen == 11 && String.first(trim) == "1" ->
String.slice trim, 1..trimlen
trimlen == 10 -> trim
true -> @invalid
end
end
@doc """
Extract the area code from a phone number
Returns the first three digits from a phone number,
ignoring long distance indicator
## Examples
iex> Phone.area_code("123-456-7890")
"123"
iex> Phone.area_code("+1 (303) 555-1212")
"303"
iex> Phone.area_code("867.5309")
"000"
"""
@spec area_code(String.t) :: String.t
def area_code(raw) do
String.slice number(raw), 0..2
end
@doc """
Pretty print a phone number
Wraps the area code in parentheses and separates
exchange and subscriber number with a dash.
## Examples
iex> Phone.pretty("123-456-7890")
"(123) 456-7890"
iex> Phone.pretty("+1 (303) 555-1212")
"(303) 555-1212"
iex> Phone.pretty("867.5309")
"(000) 000-0000"
"""
@spec pretty(String.t) :: String.t
def pretty(raw) do
clean = number(raw)
"(" <> String.slice(clean, 0..2) <> ") "
<> String.slice(clean, 3..5) <> "-"
<> String.slice(clean, 6..9)
end
end
A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.
Here are some questions to help you reflect on this solution and learn the most from it.
Community comments