From 4f65cf9c2b6a38cc55773604b8542c7e2f88b70d Mon Sep 17 00:00:00 2001 From: devkabiir <18462563+devkabiir@users.noreply.github.com> Date: Sun, 9 Apr 2023 19:08:51 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=20(concepts)=20Add=20new=20concept?= =?UTF-8?q?=20exercise=20`phone-number-analysis`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is inspired by the same in csharp track. Provides a gentle introduction to tuples. --- config.json | 14 +++ .../phone-number-analysis/.docs/hints.md | 27 +++++ .../.docs/instructions.md | 32 +++++ .../.docs/introduction.md | 114 ++++++++++++++++++ .../concept/phone-number-analysis/.gitignore | 8 ++ .../phone-number-analysis/.meta/config.json | 18 +++ .../phone-number-analysis/.meta/design.md | 23 ++++ .../phone-number-analysis/.meta/exemplar.rs | 13 ++ .../concept/phone-number-analysis/Cargo.toml | 4 + .../concept/phone-number-analysis/src/lib.rs | 7 ++ .../tests/phone-number-analysis.rs | 59 +++++++++ 11 files changed, 319 insertions(+) create mode 100644 exercises/concept/phone-number-analysis/.docs/hints.md create mode 100644 exercises/concept/phone-number-analysis/.docs/instructions.md create mode 100644 exercises/concept/phone-number-analysis/.docs/introduction.md create mode 100644 exercises/concept/phone-number-analysis/.gitignore create mode 100644 exercises/concept/phone-number-analysis/.meta/config.json create mode 100644 exercises/concept/phone-number-analysis/.meta/design.md create mode 100644 exercises/concept/phone-number-analysis/.meta/exemplar.rs create mode 100644 exercises/concept/phone-number-analysis/Cargo.toml create mode 100644 exercises/concept/phone-number-analysis/src/lib.rs create mode 100644 exercises/concept/phone-number-analysis/tests/phone-number-analysis.rs diff --git a/config.json b/config.json index 5609f8e10..b51303f28 100644 --- a/config.json +++ b/config.json @@ -35,6 +35,20 @@ }, "exercises": { "concept": [ + { + "slug": "phone-number-analysis", + "uuid": "eabea697-cc15-472f-ab4e-5b2720a180d1", + "name": "Phone Number Analysis", + "difficulty": 1, + "concepts": [ + "tuples" + ], + "prerequisites": [ + "strings", + "booleans" + ], + "status": "wip" + }, { "slug": "lucians-luscious-lasagna", "uuid": "29a2d3bd-eec8-454d-9dba-4b2d7d071925", diff --git a/exercises/concept/phone-number-analysis/.docs/hints.md b/exercises/concept/phone-number-analysis/.docs/hints.md new file mode 100644 index 000000000..7c567ad52 --- /dev/null +++ b/exercises/concept/phone-number-analysis/.docs/hints.md @@ -0,0 +1,27 @@ +# Hints + +## General + +- [Tuples][tuples]: shows how to define and use tuples. + +## 1. Analyze a phone number + +- Make sure the tuple has values at the right place. +- Tuples are passed as a [return value][tuples-return]. + +- Use `.split_at()` method on a string to split it and get a tuple of its parts. + ```rust + let str = "Per Martin-Löf"; + + let (first, last) = str.split_at(3); + + first // => "Per" + last // => " Martin-Löf" + ``` + +## 2. Detect if a phone number is fake prefix code (555) + +- You can extract the value of a field with the same sort of dot syntax as you employ with `struct`s or `class`s. + +[tuples]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type +[tuples-return]: https://docs.microsoft.com/en-us/dotnet/csharp/tuples#tuples-as-method-return-values diff --git a/exercises/concept/phone-number-analysis/.docs/instructions.md b/exercises/concept/phone-number-analysis/.docs/instructions.md new file mode 100644 index 000000000..b878604a9 --- /dev/null +++ b/exercises/concept/phone-number-analysis/.docs/instructions.md @@ -0,0 +1,32 @@ +# Instructions + +This exercise has you analyze phone numbers. + +You are asked to implement 2 features. + +Phone numbers passed to the routines are guaranteed to be in the form +NNN-NNN-NNNN e.g. 212-515-9876. + +## 1. Analyze a phone number + +Your analysis should return 3 pieces of data + +1. An indication of whether the number has a New York dialing code ie. 212 as the first 3 digits +2. An indication of whether the number is fake having 555 as a prefix code in positions 5 to 7 (numbering from 1) +3. The last 4 digits of the number. + +Implement the function `analyze()` to produce the phone number info. + +```rust +analyze("631-555-1234"); +// => (false, true, "1234") +``` + +## 2. Detect if a phone number has a fake prefix code (555) + +Implement the function `is_fake()` to detect whether the phone number is fake using the phone number info produced in task 1. + +```rust +is_fake(analyze("631-555-1234")); +// => true +``` diff --git a/exercises/concept/phone-number-analysis/.docs/introduction.md b/exercises/concept/phone-number-analysis/.docs/introduction.md new file mode 100644 index 000000000..7f7e29ed9 --- /dev/null +++ b/exercises/concept/phone-number-analysis/.docs/introduction.md @@ -0,0 +1,114 @@ +# Introduction + +## Tuples + +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. + +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. +We’ve added optional type annotations in this example: + +```rust +let my_tuple: (i32, f64, u8) = (500, 6.4, 1); +``` + +The variable `my_tuple` binds to the entire tuple because a tuple is considered +a single compound element. +To get the individual values out of a tuple, we can use pattern matching to +destructure a tuple value, like this: + +```rust +let (x, y, z) = my_tuple; + +println!("{}", y); +// => 6.4 + +``` + +This program first creates a tuple and binds it to the variable `my_tuple`. +It then uses a pattern with let to take `my_tuple` and turn it into three separate variables, `x`, `y`, and `z`. +This is called _destructuring_ because it breaks the single tuple into three +parts. +Finally, the program prints the value of `y`, which is `6.4`. + +Sometimes, when _destructuring_ a tuple, some values might not be important or +needed, these can be discarded by labeling them with "`_`" (underscore). + +```rust +let (_, y, _) = my_tuple; + +println!("{}", y); +// => 6.4 + +``` + +We can also access a tuple element directly by using a period (.) followed by the index of the value we want to access. +For example: + +```rust +let my_tuple: (i32, f64, u8) = (500, 6.4, 1); + +let five_hundred = my_tuple.0; + +let six_point_four = my_tuple.1; + +let one = my_tuple.2; +``` + +This program creates the tuple `my_tuple` and then accesses each of its elements using their respective indices. +As with most programming languages, the first index in a tuple is 0. + +A tuple can contain 0, or upto 12 elements. A tuple with zero elements has a +special name, _unit_. + +```rust +let my_zero_tuple = (); +let my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); +``` + +### Calling methods +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. + +```rust +let my_tuple = (12, "hello"); + +let (my_num, my_str) = my_tuple; + +my_str.to_uppercase(); + +// OR + +my_tuple.1.to_uppercase(); +``` + +### Functions can accept a tuple as a parameter. +Accepting a tuple as a parameter requires to explicitly define its type. The +following example illustrates that. + +```rust +fn my_function(my_tuple: (i32, &str)) { + // Do something with my_tuple +} +``` + +### Functions can return tuple as a result. +Returning a tuple as a result requires to explicitly define its type. The +following example illustrates that. + +```rust +fn make_tuple(an_int: i32, a_string: &str) -> (i32, &str) { + return (an_int, a_string); +} +``` + +### Methods can return tuple as a result. +Methods on various types sometimes return a tuple as a result. Consider the +following example of a `&str` variable's `.split_at()` method. + +```rust +let str = "Per Martin-Löf"; + +let (first, last) = str.split_at(3); + +first // => "Per" +last // => " Martin-Löf" +``` diff --git a/exercises/concept/phone-number-analysis/.gitignore b/exercises/concept/phone-number-analysis/.gitignore new file mode 100644 index 000000000..db7f315c0 --- /dev/null +++ b/exercises/concept/phone-number-analysis/.gitignore @@ -0,0 +1,8 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +**/*.rs.bk + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/exercises/concept/phone-number-analysis/.meta/config.json b/exercises/concept/phone-number-analysis/.meta/config.json new file mode 100644 index 000000000..0e97f7fd9 --- /dev/null +++ b/exercises/concept/phone-number-analysis/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "devkabiir" + ], + "files": { + "solution": [ + "src/lib.rs", + "Cargo.toml" + ], + "test": [ + "tests/phone-number-analysis.rs" + ], + "exemplar": [ + ".meta/exemplar.rs" + ] + }, + "blurb": "Learn about tuples by analysing phone numbers." +} diff --git a/exercises/concept/phone-number-analysis/.meta/design.md b/exercises/concept/phone-number-analysis/.meta/design.md new file mode 100644 index 000000000..bc6ad0560 --- /dev/null +++ b/exercises/concept/phone-number-analysis/.meta/design.md @@ -0,0 +1,23 @@ +# Design + +## Learning objectives + +- Know of the existence of tuples. +- Know how to assigne a tuple. +- Know how to access a value held by a tuple. +- Know how to return a tuple as a result. +- Know how to destructure tuple values into variables. +- Know how to accept a tuple as a parameter. + +## Out of scope + + +## Concepts + +- `tuples` + +## Prerequisites + +- `strings` +- `if-statements` +- `booleans` diff --git a/exercises/concept/phone-number-analysis/.meta/exemplar.rs b/exercises/concept/phone-number-analysis/.meta/exemplar.rs new file mode 100644 index 000000000..8362b67aa --- /dev/null +++ b/exercises/concept/phone-number-analysis/.meta/exemplar.rs @@ -0,0 +1,13 @@ +pub fn analyze(phone_number: &str) -> (bool, bool, &str) { + let (dial_code, number) = phone_number.split_at(3); + + let (prefix_code, last_4_with_dash) = number.split_at(4); + + let (_, last_4) = last_4_with_dash.split_at(1); + + (dial_code == "212", prefix_code == "-555", last_4) +} + +pub fn is_fake(info: (bool, bool, &str)) -> bool { + info.1 +} diff --git a/exercises/concept/phone-number-analysis/Cargo.toml b/exercises/concept/phone-number-analysis/Cargo.toml new file mode 100644 index 000000000..5bad8ff6d --- /dev/null +++ b/exercises/concept/phone-number-analysis/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "phone_number_analysis" +version = "0.1.0" +edition = "2021" diff --git a/exercises/concept/phone-number-analysis/src/lib.rs b/exercises/concept/phone-number-analysis/src/lib.rs new file mode 100644 index 000000000..5a789e7cf --- /dev/null +++ b/exercises/concept/phone-number-analysis/src/lib.rs @@ -0,0 +1,7 @@ +pub fn analyze(_phone_number: &str) -> (bool, bool, &str) { + unimplemented!("Implement analyze") +} + +pub fn is_fake(_info: (bool, bool, &str)) -> bool { + unimplemented!("Implement is_fake") +} diff --git a/exercises/concept/phone-number-analysis/tests/phone-number-analysis.rs b/exercises/concept/phone-number-analysis/tests/phone-number-analysis.rs new file mode 100644 index 000000000..034a2968a --- /dev/null +++ b/exercises/concept/phone-number-analysis/tests/phone-number-analysis.rs @@ -0,0 +1,59 @@ +#[test] +pub fn analyze_non_fake_non_newyork() { + assert_eq!( + (false, false, "1234"), + phone_number_analysis::analyze("631-502-1234") + ); +} + +#[test] +#[ignore] +pub fn analyze_fake_non_newyork() { + assert_eq!( + (false, true, "1234"), + phone_number_analysis::analyze("631-555-1234") + ); +} + +#[test] +#[ignore] +pub fn analyze_non_fake_newyork() { + assert_eq!( + (true, false, "1234"), + phone_number_analysis::analyze("212-502-1234") + ); +} + +#[test] +#[ignore] +pub fn analyze_fake_newyork() { + assert_eq!( + (true, true, "1234"), + phone_number_analysis::analyze("212-555-1234") + ); +} + +#[test] +#[ignore] +pub fn analyze_fake_fake() { + assert_eq!( + (false, false, "1234"), + phone_number_analysis::analyze("515-212-1234") + ); +} + +#[test] +#[ignore] +pub fn is_fake_fake() { + assert!(phone_number_analysis::is_fake( + phone_number_analysis::analyze("212-555-1234") + )); +} + +#[test] +#[ignore] +pub fn is_fake_non_fake() { + assert!(!phone_number_analysis::is_fake( + phone_number_analysis::analyze("555-212-1234") + )); +}