Skip to content

Commit 4f65cf9

Browse files
committed
✨ (concepts) Add new concept exercise phone-number-analysis
This is inspired by the same in csharp track. Provides a gentle introduction to tuples.
1 parent 796f2ca commit 4f65cf9

File tree

11 files changed

+319
-0
lines changed

11 files changed

+319
-0
lines changed

config.json

+14
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@
3535
},
3636
"exercises": {
3737
"concept": [
38+
{
39+
"slug": "phone-number-analysis",
40+
"uuid": "eabea697-cc15-472f-ab4e-5b2720a180d1",
41+
"name": "Phone Number Analysis",
42+
"difficulty": 1,
43+
"concepts": [
44+
"tuples"
45+
],
46+
"prerequisites": [
47+
"strings",
48+
"booleans"
49+
],
50+
"status": "wip"
51+
},
3852
{
3953
"slug": "lucians-luscious-lasagna",
4054
"uuid": "29a2d3bd-eec8-454d-9dba-4b2d7d071925",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Hints
2+
3+
## General
4+
5+
- [Tuples][tuples]: shows how to define and use tuples.
6+
7+
## 1. Analyze a phone number
8+
9+
- Make sure the tuple has values at the right place.
10+
- Tuples are passed as a [return value][tuples-return].
11+
12+
- Use `.split_at()` method on a string to split it and get a tuple of its parts.
13+
```rust
14+
let str = "Per Martin-Löf";
15+
16+
let (first, last) = str.split_at(3);
17+
18+
first // => "Per"
19+
last // => " Martin-Löf"
20+
```
21+
22+
## 2. Detect if a phone number is fake prefix code (555)
23+
24+
- You can extract the value of a field with the same sort of dot syntax as you employ with `struct`s or `class`s.
25+
26+
[tuples]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
27+
[tuples-return]: https://docs.microsoft.com/en-us/dotnet/csharp/tuples#tuples-as-method-return-values
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Instructions
2+
3+
This exercise has you analyze phone numbers.
4+
5+
You are asked to implement 2 features.
6+
7+
Phone numbers passed to the routines are guaranteed to be in the form
8+
NNN-NNN-NNNN e.g. 212-515-9876.
9+
10+
## 1. Analyze a phone number
11+
12+
Your analysis should return 3 pieces of data
13+
14+
1. An indication of whether the number has a New York dialing code ie. 212 as the first 3 digits
15+
2. An indication of whether the number is fake having 555 as a prefix code in positions 5 to 7 (numbering from 1)
16+
3. The last 4 digits of the number.
17+
18+
Implement the function `analyze()` to produce the phone number info.
19+
20+
```rust
21+
analyze("631-555-1234");
22+
// => (false, true, "1234")
23+
```
24+
25+
## 2. Detect if a phone number has a fake prefix code (555)
26+
27+
Implement the function `is_fake()` to detect whether the phone number is fake using the phone number info produced in task 1.
28+
29+
```rust
30+
is_fake(analyze("631-555-1234"));
31+
// => true
32+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Introduction
2+
3+
## Tuples
4+
5+
A _tuple_ is a general way of grouping together a number of values with a variety of types into one compound type. Tuples have a fixed length: once declared, they cannot grow or shrink in size.
6+
7+
We create a tuple by writing a comma-separated list of values inside parentheses. Each position in the tuple has a type, and the types of the different values in the tuple don’t have to be the same.
8+
We’ve added optional type annotations in this example:
9+
10+
```rust
11+
let my_tuple: (i32, f64, u8) = (500, 6.4, 1);
12+
```
13+
14+
The variable `my_tuple` binds to the entire tuple because a tuple is considered
15+
a single compound element.
16+
To get the individual values out of a tuple, we can use pattern matching to
17+
destructure a tuple value, like this:
18+
19+
```rust
20+
let (x, y, z) = my_tuple;
21+
22+
println!("{}", y);
23+
// => 6.4
24+
25+
```
26+
27+
This program first creates a tuple and binds it to the variable `my_tuple`.
28+
It then uses a pattern with let to take `my_tuple` and turn it into three separate variables, `x`, `y`, and `z`.
29+
This is called _destructuring_ because it breaks the single tuple into three
30+
parts.
31+
Finally, the program prints the value of `y`, which is `6.4`.
32+
33+
Sometimes, when _destructuring_ a tuple, some values might not be important or
34+
needed, these can be discarded by labeling them with "`_`" (underscore).
35+
36+
```rust
37+
let (_, y, _) = my_tuple;
38+
39+
println!("{}", y);
40+
// => 6.4
41+
42+
```
43+
44+
We can also access a tuple element directly by using a period (.) followed by the index of the value we want to access.
45+
For example:
46+
47+
```rust
48+
let my_tuple: (i32, f64, u8) = (500, 6.4, 1);
49+
50+
let five_hundred = my_tuple.0;
51+
52+
let six_point_four = my_tuple.1;
53+
54+
let one = my_tuple.2;
55+
```
56+
57+
This program creates the tuple `my_tuple` and then accesses each of its elements using their respective indices.
58+
As with most programming languages, the first index in a tuple is 0.
59+
60+
A tuple can contain 0, or upto 12 elements. A tuple with zero elements has a
61+
special name, _unit_.
62+
63+
```rust
64+
let my_zero_tuple = ();
65+
let my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
66+
```
67+
68+
### Calling methods
69+
One can call any methods on a value held by a tuple by either first destructuring that value out of the tuple or accessing it using it's index.
70+
71+
```rust
72+
let my_tuple = (12, "hello");
73+
74+
let (my_num, my_str) = my_tuple;
75+
76+
my_str.to_uppercase();
77+
78+
// OR
79+
80+
my_tuple.1.to_uppercase();
81+
```
82+
83+
### Functions can accept a tuple as a parameter.
84+
Accepting a tuple as a parameter requires to explicitly define its type. The
85+
following example illustrates that.
86+
87+
```rust
88+
fn my_function(my_tuple: (i32, &str)) {
89+
// Do something with my_tuple
90+
}
91+
```
92+
93+
### Functions can return tuple as a result.
94+
Returning a tuple as a result requires to explicitly define its type. The
95+
following example illustrates that.
96+
97+
```rust
98+
fn make_tuple(an_int: i32, a_string: &str) -> (i32, &str) {
99+
return (an_int, a_string);
100+
}
101+
```
102+
103+
### Methods can return tuple as a result.
104+
Methods on various types sometimes return a tuple as a result. Consider the
105+
following example of a `&str` variable's `.split_at()` method.
106+
107+
```rust
108+
let str = "Per Martin-Löf";
109+
110+
let (first, last) = str.split_at(3);
111+
112+
first // => "Per"
113+
last // => " Martin-Löf"
114+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
**/*.rs.bk
5+
6+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7+
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8+
Cargo.lock
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"authors": [
3+
"devkabiir"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/lib.rs",
8+
"Cargo.toml"
9+
],
10+
"test": [
11+
"tests/phone-number-analysis.rs"
12+
],
13+
"exemplar": [
14+
".meta/exemplar.rs"
15+
]
16+
},
17+
"blurb": "Learn about tuples by analysing phone numbers."
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Design
2+
3+
## Learning objectives
4+
5+
- Know of the existence of tuples.
6+
- Know how to assigne a tuple.
7+
- Know how to access a value held by a tuple.
8+
- Know how to return a tuple as a result.
9+
- Know how to destructure tuple values into variables.
10+
- Know how to accept a tuple as a parameter.
11+
12+
## Out of scope
13+
14+
15+
## Concepts
16+
17+
- `tuples`
18+
19+
## Prerequisites
20+
21+
- `strings`
22+
- `if-statements`
23+
- `booleans`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
pub fn analyze(phone_number: &str) -> (bool, bool, &str) {
2+
let (dial_code, number) = phone_number.split_at(3);
3+
4+
let (prefix_code, last_4_with_dash) = number.split_at(4);
5+
6+
let (_, last_4) = last_4_with_dash.split_at(1);
7+
8+
(dial_code == "212", prefix_code == "-555", last_4)
9+
}
10+
11+
pub fn is_fake(info: (bool, bool, &str)) -> bool {
12+
info.1
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[package]
2+
name = "phone_number_analysis"
3+
version = "0.1.0"
4+
edition = "2021"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub fn analyze(_phone_number: &str) -> (bool, bool, &str) {
2+
unimplemented!("Implement analyze")
3+
}
4+
5+
pub fn is_fake(_info: (bool, bool, &str)) -> bool {
6+
unimplemented!("Implement is_fake")
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#[test]
2+
pub fn analyze_non_fake_non_newyork() {
3+
assert_eq!(
4+
(false, false, "1234"),
5+
phone_number_analysis::analyze("631-502-1234")
6+
);
7+
}
8+
9+
#[test]
10+
#[ignore]
11+
pub fn analyze_fake_non_newyork() {
12+
assert_eq!(
13+
(false, true, "1234"),
14+
phone_number_analysis::analyze("631-555-1234")
15+
);
16+
}
17+
18+
#[test]
19+
#[ignore]
20+
pub fn analyze_non_fake_newyork() {
21+
assert_eq!(
22+
(true, false, "1234"),
23+
phone_number_analysis::analyze("212-502-1234")
24+
);
25+
}
26+
27+
#[test]
28+
#[ignore]
29+
pub fn analyze_fake_newyork() {
30+
assert_eq!(
31+
(true, true, "1234"),
32+
phone_number_analysis::analyze("212-555-1234")
33+
);
34+
}
35+
36+
#[test]
37+
#[ignore]
38+
pub fn analyze_fake_fake() {
39+
assert_eq!(
40+
(false, false, "1234"),
41+
phone_number_analysis::analyze("515-212-1234")
42+
);
43+
}
44+
45+
#[test]
46+
#[ignore]
47+
pub fn is_fake_fake() {
48+
assert!(phone_number_analysis::is_fake(
49+
phone_number_analysis::analyze("212-555-1234")
50+
));
51+
}
52+
53+
#[test]
54+
#[ignore]
55+
pub fn is_fake_non_fake() {
56+
assert!(!phone_number_analysis::is_fake(
57+
phone_number_analysis::analyze("555-212-1234")
58+
));
59+
}

0 commit comments

Comments
 (0)