ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# angelikatyborska's solution

## to Phone Number in the Elixir Track

Published at May 01 2021 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

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.

## Running tests

Execute the tests with:

``````\$ elixir phone_number_test.exs
``````

### Pending tests

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

If you're stuck on something, it may help to look at some of the available resources out there where answers might be found.

## Source

Event Manager by JumpstartLab http://tutorials.jumpstartlab.com/projects/eventmanager.html

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### phone_number_test.exs

``````if !System.get_env("EXERCISM_TEST_EXAMPLES") do
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
defstruct country_code: "1", area_code: "000", exchange_code: "000", subscriber_number: "0000"

@country_code "\\\+?1"
@area_code "[2-9][0-9]{2}"
@exchange_code "[2-9][0-9]{2}"
@subscriber_number "[0-9]{4}"
@delimiter "[\\p{P}\\s]*"
@phone_number ~r/^(#{@country_code})?#{@delimiter}(#{@area_code})#{@delimiter}(#{@exchange_code})#{
@delimiter
}(#{@subscriber_number})\$/

@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("212-555-0100")
"2125550100"

iex> Phone.number("+1 (212) 555-0100")
"2125550100"

iex> Phone.number("+1 (212) 055-0100")
"0000000000"

iex> Phone.number("(212) 555-0100")
"2125550100"

iex> Phone.number("867.5309")
"0000000000"
"""
@spec number(String.t()) :: String.t()
def number(raw) do
%Phone{
area_code: area_code,
exchange_code: exchange_code,
subscriber_number: subscriber_number
} = get_phone(raw)

"#{area_code}#{exchange_code}#{subscriber_number}"
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("212-555-0100")
"212"

iex> Phone.area_code("+1 (212) 555-0100")
"212"

iex> Phone.area_code("+1 (012) 555-0100")
"000"

iex> Phone.area_code("867.5309")
"000"
"""
@spec area_code(String.t()) :: String.t()
def area_code(raw) do
%Phone{area_code: area_code} = get_phone(raw)

area_code
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("212-555-0100")
"(212) 555-0100"

iex> Phone.pretty("212-155-0100")
"(000) 000-0000"

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
%Phone{
area_code: area_code,
exchange_code: exchange_code,
subscriber_number: subscriber_number
} = get_phone(raw)

"(#{area_code}) #{exchange_code}-#{subscriber_number}"
end

defp get_phone(raw) do
case Regex.run(@phone_number, raw) do
[_, country_code, area_code, exchange_code, subscriber_number] ->
%Phone{
country_code: country_code,
area_code: area_code,
exchange_code: exchange_code,
subscriber_number: subscriber_number
}

_ ->
%Phone{}
end
end
end``````