Skip to content

Commit 39f7b8a

Browse files
authored
Merge pull request #447 from keiravillekode/phone-number
Add phone-number exercise
2 parents 5a027b9 + 4088d13 commit 39f7b8a

File tree

8 files changed

+311
-0
lines changed

8 files changed

+311
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,14 @@
270270
"prerequisites": [],
271271
"difficulty": 4
272272
},
273+
{
274+
"slug": "phone-number",
275+
"name": "Phone Number",
276+
"uuid": "66cd0755-1817-4ae3-9c5f-fab39bb08065",
277+
"practices": [],
278+
"prerequisites": [],
279+
"difficulty": 3
280+
},
273281
{
274282
"slug": "isogram",
275283
"name": "Isogram",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Instructions
2+
3+
Clean up user-entered phone numbers so that they can be sent SMS messages.
4+
5+
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.
6+
All NANP-countries share the same international country code: `1`.
7+
8+
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.
9+
The first three digits of the local number represent the _exchange code_, followed by the unique four-digit number which is the _subscriber number_.
10+
11+
The format is usually represented as
12+
13+
```text
14+
NXX NXX-XXXX
15+
```
16+
17+
where `N` is any digit from 2 through 9 and `X` is any digit from 0 through 9.
18+
19+
Sometimes they also have the country code (represented as `1` or `+1`) prefixed.
20+
21+
Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code if present.
22+
23+
For example, the inputs
24+
25+
- `+1 (613)-995-0253`
26+
- `613-995-0253`
27+
- `1 613 995 0253`
28+
- `613.995.0253`
29+
30+
should all produce the output
31+
32+
`6139950253`
33+
34+
**Note:** As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Introduction
2+
3+
You've joined LinkLine, a leading communications company working to ensure reliable connections for everyone.
4+
The team faces a big challenge: users submit phone numbers in all sorts of formats — dashes, spaces, dots, parentheses, and even prefixes.
5+
Some numbers are valid, while others are impossible to use.
6+
7+
Your mission is to turn this chaos into order.
8+
You'll clean up valid numbers, formatting them appropriately for use in the system.
9+
At the same time, you'll identify and filter out any invalid entries.
10+
11+
The success of LinkLine's operations depends on your ability to separate the useful from the unusable.
12+
Are you ready to take on the challenge and keep the connections running smoothly?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"phone_number.zig"
8+
],
9+
"test": [
10+
"test_phone_number.zig"
11+
],
12+
"example": [
13+
".meta/example.zig"
14+
]
15+
},
16+
"blurb": "Clean up user-entered phone numbers so that they can be sent SMS messages.",
17+
"source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.",
18+
"source_url": "https://turing.edu"
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
pub fn clean(phrase: []const u8) ?[10]u8 {
2+
var result: [10]u8 = undefined;
3+
var leading_one = false;
4+
var index: usize = 0;
5+
for (phrase) |digit| {
6+
if (digit < '0') {
7+
// Ignore whitespace and ( ) + -
8+
continue;
9+
}
10+
11+
if (digit > '9') {
12+
// Reject letters and punctuation like @
13+
return null;
14+
}
15+
16+
if (index == 0 and digit == '1') {
17+
if (leading_one) {
18+
return null;
19+
}
20+
21+
leading_one = true;
22+
continue;
23+
}
24+
25+
if (index == 10) {
26+
return null;
27+
}
28+
29+
result[index] = digit;
30+
index += 1;
31+
}
32+
33+
if (index != 10 or result[0] < '2' or result[3] < '2') {
34+
return null;
35+
}
36+
37+
return result;
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[79666dce-e0f1-46de-95a1-563802913c35]
13+
description = "cleans the number"
14+
15+
[c360451f-549f-43e4-8aba-fdf6cb0bf83f]
16+
description = "cleans numbers with dots"
17+
18+
[08f94c34-9a37-46a2-a123-2a8e9727395d]
19+
description = "cleans numbers with multiple spaces"
20+
21+
[598d8432-0659-4019-a78b-1c6a73691d21]
22+
description = "invalid when 9 digits"
23+
include = false
24+
25+
[2de74156-f646-42b5-8638-0ef1d8b58bc2]
26+
description = "invalid when 9 digits"
27+
reimplements = "598d8432-0659-4019-a78b-1c6a73691d21"
28+
29+
[57061c72-07b5-431f-9766-d97da7c4399d]
30+
description = "invalid when 11 digits does not start with a 1"
31+
32+
[9962cbf3-97bb-4118-ba9b-38ff49c64430]
33+
description = "valid when 11 digits and starting with 1"
34+
35+
[fa724fbf-054c-4d91-95da-f65ab5b6dbca]
36+
description = "valid when 11 digits and starting with 1 even with punctuation"
37+
38+
[c6a5f007-895a-4fc5-90bc-a7e70f9b5cad]
39+
description = "invalid when more than 11 digits"
40+
include = false
41+
42+
[4a1509b7-8953-4eec-981b-c483358ff531]
43+
description = "invalid when more than 11 digits"
44+
reimplements = "c6a5f007-895a-4fc5-90bc-a7e70f9b5cad"
45+
46+
[63f38f37-53f6-4a5f-bd86-e9b404f10a60]
47+
description = "invalid with letters"
48+
include = false
49+
50+
[eb8a1fc0-64e5-46d3-b0c6-33184208e28a]
51+
description = "invalid with letters"
52+
reimplements = "63f38f37-53f6-4a5f-bd86-e9b404f10a60"
53+
54+
[4bd97d90-52fd-45d3-b0db-06ab95b1244e]
55+
description = "invalid with punctuations"
56+
include = false
57+
58+
[065f6363-8394-4759-b080-e6c8c351dd1f]
59+
description = "invalid with punctuations"
60+
reimplements = "4bd97d90-52fd-45d3-b0db-06ab95b1244e"
61+
62+
[d77d07f8-873c-4b17-8978-5f66139bf7d7]
63+
description = "invalid if area code starts with 0"
64+
65+
[c7485cfb-1e7b-4081-8e96-8cdb3b77f15e]
66+
description = "invalid if area code starts with 1"
67+
68+
[4d622293-6976-413d-b8bf-dd8a94d4e2ac]
69+
description = "invalid if exchange code starts with 0"
70+
71+
[4cef57b4-7d8e-43aa-8328-1e1b89001262]
72+
description = "invalid if exchange code starts with 1"
73+
74+
[9925b09c-1a0d-4960-a197-5d163cbe308c]
75+
description = "invalid if area code starts with 0 on valid 11-digit number"
76+
77+
[3f809d37-40f3-44b5-ad90-535838b1a816]
78+
description = "invalid if area code starts with 1 on valid 11-digit number"
79+
80+
[e08e5532-d621-40d4-b0cc-96c159276b65]
81+
description = "invalid if exchange code starts with 0 on valid 11-digit number"
82+
83+
[57b32f3d-696a-455c-8bf1-137b6d171cdf]
84+
description = "invalid if exchange code starts with 1 on valid 11-digit number"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub fn clean(phrase: []const u8) ?[10]u8 {
2+
_ = phrase;
3+
@compileError("please implement the clean function");
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
const std = @import("std");
2+
const testing = std.testing;
3+
4+
const phone_number = @import("phone_number.zig");
5+
6+
test "cleans the number" {
7+
const expected: ?[10]u8 = "2234567890".*;
8+
const actual = phone_number.clean("(223) 456-7890");
9+
try testing.expectEqual(expected, actual);
10+
}
11+
12+
test "cleans numbers with dots" {
13+
const expected: ?[10]u8 = "2234567890".*;
14+
const actual = phone_number.clean("223.456.7890");
15+
try testing.expectEqual(expected, actual);
16+
}
17+
18+
test "cleans numbers with multiple spaces" {
19+
const expected: ?[10]u8 = "2234567890".*;
20+
const actual = phone_number.clean("223 456 7890 ");
21+
try testing.expectEqual(expected, actual);
22+
}
23+
24+
test "invalid when 9 digits" {
25+
const expected: ?[10]u8 = null;
26+
const actual = phone_number.clean("123456789");
27+
try testing.expectEqual(expected, actual);
28+
}
29+
30+
test "invalid when 11 digits does not start with a 1" {
31+
const expected: ?[10]u8 = null;
32+
const actual = phone_number.clean("22234567890");
33+
try testing.expectEqual(expected, actual);
34+
}
35+
36+
test "valid when 11 digits and starting with 1" {
37+
const expected: ?[10]u8 = "2234567890".*;
38+
const actual = phone_number.clean("12234567890");
39+
try testing.expectEqual(expected, actual);
40+
}
41+
42+
test "valid when 11 digits and starting with 1 even with punctuation" {
43+
const expected: ?[10]u8 = "2234567890".*;
44+
const actual = phone_number.clean("+1 (223) 456-7890");
45+
try testing.expectEqual(expected, actual);
46+
}
47+
48+
test "invalid when more than 11 digits" {
49+
const expected: ?[10]u8 = null;
50+
const actual = phone_number.clean("321234567890");
51+
try testing.expectEqual(expected, actual);
52+
}
53+
54+
test "invalid with letters" {
55+
const expected: ?[10]u8 = null;
56+
const actual = phone_number.clean("523-abc-7890");
57+
try testing.expectEqual(expected, actual);
58+
}
59+
60+
test "invalid with punctuations" {
61+
const expected: ?[10]u8 = null;
62+
const actual = phone_number.clean("523-@:!-7890");
63+
try testing.expectEqual(expected, actual);
64+
}
65+
66+
test "invalid if area code starts with 0" {
67+
const expected: ?[10]u8 = null;
68+
const actual = phone_number.clean("(023) 456-7890");
69+
try testing.expectEqual(expected, actual);
70+
}
71+
72+
test "invalid if area code starts with 1" {
73+
const expected: ?[10]u8 = null;
74+
const actual = phone_number.clean("(123) 456-7890");
75+
try testing.expectEqual(expected, actual);
76+
}
77+
78+
test "invalid if exchange code starts with 0" {
79+
const expected: ?[10]u8 = null;
80+
const actual = phone_number.clean("(223) 056-7890");
81+
try testing.expectEqual(expected, actual);
82+
}
83+
84+
test "invalid if exchange code starts with 1" {
85+
const expected: ?[10]u8 = null;
86+
const actual = phone_number.clean("(223) 156-7890");
87+
try testing.expectEqual(expected, actual);
88+
}
89+
90+
test "invalid if area code starts with 0 on valid 11-digit number" {
91+
const expected: ?[10]u8 = null;
92+
const actual = phone_number.clean("1 (023) 456-7890");
93+
try testing.expectEqual(expected, actual);
94+
}
95+
96+
test "invalid if area code starts with 1 on valid 11-digit number" {
97+
const expected: ?[10]u8 = null;
98+
const actual = phone_number.clean("1 (123) 456-7890");
99+
try testing.expectEqual(expected, actual);
100+
}
101+
102+
test "invalid if exchange code starts with 0 on valid 11-digit number" {
103+
const expected: ?[10]u8 = null;
104+
const actual = phone_number.clean("1 (223) 056-7890");
105+
try testing.expectEqual(expected, actual);
106+
}
107+
108+
test "invalid if exchange code starts with 1 on valid 11-digit number" {
109+
const expected: ?[10]u8 = null;
110+
const actual = phone_number.clean("1 (223) 156-7890");
111+
try testing.expectEqual(expected, actual);
112+
}

0 commit comments

Comments
 (0)