Browse Source

Merge pull request #756 from 01-edu/rust-subject-review-quest-07

first pass
pull/762/head
augusto-mantilla 3 years ago committed by GitHub
parent
commit
3086ead9bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 52
      subjects/borrow_box/README.md
  2. 38
      subjects/box_it/README.md
  3. 35
      subjects/box_recursion/README.md
  4. 28
      subjects/drop_the_thread/README.md
  5. 24
      subjects/how_many_references/README.md
  6. 66
      subjects/ref_cell/README.md

52
subjects/borrow_box/README.md

@ -2,22 +2,26 @@
### Instructions
You will have to create a **CRUD** functionality. Therefore creating the following functions :
In this exercise, a **CRUD** functionality will have to be created. Therefore the following functions will have to be defined :
- `new`, that receives two players and initializes them with a name and a score. This functions should
- `new`, which receives two players and initializes them with a name and a score. This functions should
return the structure wrapped in a Box.
- `read_winner`, returns a tuple with the name and the score of the player who is winning.
- `read_winner`, which returns a tuple with the name and the score of the player who is winning.
In case none of the players are winning, it should return the same tuple with the string "Same score! tied" and the tied score.
- `update_score`, that receives the name of a player.
This function should increment the score of the player. The score should only be increased if it does not pass the `nbr_of_games`.
Example: if the nbr_of_games is 3 then the game should be best out of three. So if one play as 2 wins then
he is the winner and the function should not increase the score anymore for either players.
- `update_score`, which receives the name of a player.
This function should increment the score of the player. The score should only be increased if it does not pass the `nbr_of_games`.
Example: if the nbr_of_games is 3 then the winner of the game should be the one who is the best out of three games. So if one play as 2 wins then
he is the winner and the function should not increase the score anymore for either players.
- `delete`, that takes the ownership of the boxed game and returning a string : "Game deleted: id -> 0".
- `delete`, which takes the ownership of the boxed game and returning a string : "Game deleted: id -> 0".
### Expected Function
### Notions
- [Box Pointers](https://doc.rust-lang.org/book/ch15-01-box.html)
### Expected Functions
```rust
#[derive(Debug, Clone, Eq, PartialEq)]
@ -25,20 +29,30 @@ pub struct Game {
// expected public fields
}
impl Game {
pub fn new(i: u32, pl1: String, pl2: String, n: u16) -> Box<Game> {}
pub fn read_winner(&self) -> (String, u16) {}
pub fn update_score(&mut self, user_name: String) {}
pub fn delete(self) -> String {}
pub fn new(i: u32, pl1: String, pl2: String, n: u16) -> Box<Game> {
}
pub fn read_winner(&self) -> (String, u16) {
}
pub fn update_score(&mut self, user_name: String) {
}
pub fn delete(self) -> String {
}
}
```
### Usage
Here is a program to test your function
Here is a program to test your functions,
```rust
use borrow_box::*;
fn main() {
let mut game = Game::create_game(0, String::from("Joao"), String::from("Susana"), 5);
let mut game = Game::new(0, String::from("Joao"), String::from("Susana"), 5);
println!("{:?}", game.read_winner());
// output : ("Same score! tied", 0)
@ -52,11 +66,10 @@ fn main() {
game.update_score(String::from("Joao"));
// this one will not count because it already 5 games played, the nbr_of_games
game.update_score(String::from("Susana"));
println!("{:?}", game.read_winner());
// output : ("Joao", 3)
game.delete();
println!("{:?}", game.delete());
// output : "game deleted: id -> 0"
@ -76,8 +89,3 @@ student@ubuntu:~/[[ROOT]]/test$ cargo run
"game deleted: id -> 0"
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/book/ch15-01-box.html

38
subjects/box_it/README.md

@ -2,25 +2,36 @@
### Instructions
Create the following functions:
Create the following **functions**:
- `transform_and_save_on_heap`, that receives a string with a number (that can or not have a k (kilo) suffix)
and transforms those numbers into `u32` and inserts it into a vector that must be saved in the heap using **Box**.
- `transform_and_save_on_heap`, which receives a string with a number (that can or not have a k (kilo) suffix)
and transforms those numbers into `u32` and inserts them into a vector which must be saved in the heap using **Box**.
- `take_value_ownership`, that takes the value (unboxed value) form the box and returns it
- `take_value_ownership`, which takes the value (unboxed value) from the box and returns it
### Expected Function
### Notions
- [smart pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html)
- [using box](https://doc.rust-lang.org/book/ch15-01-box.html)
### Expected Functions
```rust
pub fn transform_and_save_on_heap(s: String) -> Box<Vec<u32>> {}
pub fn take_value_ownership(a: Box<Vec<u32>>) -> Vec<u32> {}
pub fn transform_and_save_on_heap(s: String) -> Box<Vec<u32>> {
}
pub fn take_value_ownership(a: Box<Vec<u32>>) -> Vec<u32> {
}
```
### Usage
Here is a program to test your function
Here is a program to test your functions
```rust
use box_it::*;
fn main() {
let new_str = String::from("5.5k 8.9k 32");
@ -28,7 +39,7 @@ fn main() {
let a_h = transform_and_save_on_heap(new_str);
println!("Box value : {:?}", &a_h);
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_h)));
let a_b_v = take_value_ownership(a_h);
println!("value : {:?}", &a_b_v);
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_b_v)));
@ -40,14 +51,9 @@ And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
Box value : [6800, 13500]
Box value : [5500, 8900, 32]
size occupied in the stack : 8 bytes
value : [6800, 13500]
value : [5500, 8900, 32]
size occupied in the stack : 24 bytes
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/book/ch15-00-smart-pointers.html
- https://doc.rust-lang.org/book/ch15-01-box.html

35
subjects/box_recursion/README.md

@ -2,25 +2,31 @@
### Instructions
Using the given code create the following functions:
Using the given code create the following **functions**:
- `new` that will initialize the `WorkEnvironment` as `None`
- `add_worker`, that receives two strings, one being the type of worker and the other the name of the worker.
- `remove_worker`, that removes the last worker that was placed in the `WorkEnvironment`, this functions should
return a `Option` with the name of the worker.
- `search_worker`, that return a tuple with the name and type of worker.
- `new` which will initialize the `WorkEnvironment` as `None`
- `add_worker`, which receives two strings, one being the type of worker and the other the name of the worker.
- `remove_worker`, which removes the last worker that was placed in the `WorkEnvironment`, this function should
returns an `Option` with the name of the worker.
- `search_worker`, which returns a tuple with the name and type of worker.
You must also create a type called `Link` this will be the connection of the structures `WorkEnvironment` and `Worker`.
You must also create a type called `Link`. This will be the connection of the structures `WorkEnvironment` and `Worker`.
Do not forget that this will be a recursion type and it must point to `None` if there is no workers.
### Expected Function
### Notions
- [enum](https://doc.rust-lang.org/rust-by-example/custom_types/enum.html)
- [boc](https://doc.rust-lang.org/book/ch15-01-box.html)
- [Module std::option](https://doc.rust-lang.org/std/option/)
### Expected Functions and structures
```rust
pub struct WorkEnvironment {
pub grade: Link,
}
pub type Link =
pub type Link =
pub struct Worker {
pub worker_type: String,
@ -40,9 +46,11 @@ impl WorkEnvironment {
### Usage
Here is a program to test your function
Here is a program to test your function,
```rust
use box_recursion::*;
fn main() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
@ -70,10 +78,3 @@ Some(("Alice", "Normal Worker"))
WorkEnvironment { grade: None }
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/rust-by-example/custom_types/enum.html
- https://doc.rust-lang.org/book/ch15-01-box.html
- https://doc.rust-lang.org/std/option/
- https://doc.rust-lang.org/book/ch15-01-box.html

28
subjects/drop_the_thread/README.md

@ -4,20 +4,23 @@
"Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data"
You must create a Drop checker API. For this you must create:
in this exercise a Drop checker API has to be created. For this you must define:
- Two structures:
- `Workers` that will have two fields:
- `drops` that will save the number of dropped threads
- `drops` that will save the number of dropped threads.
- `states` that will save a state of multiple threads.
If the thread is not dropped, the state will be false otherwise true.
- `Thread` that will have the following fields:
- `pid`, the id of the thread
- `cmd`, the name of the thread
- `pid`, the id of the thread.
- `cmd`, the name of the thread.
- `parent`, that will be the link to the structure `Workers` (Tip: this must be a reference to the structure Workers)
- Implementation of each structure:
- `Workers` :
- `new`, that creates a default worker
- `new_worker`, that returns a tuple with the `pid` and a new `Thread`,
this function must receive a `String` being the `cmd`
@ -33,7 +36,13 @@ You must create a Drop checker API. For this you must create:
- You must implement for the structure `Thread` the `Drop` trait. In this trait you must call the function `add_drop` so that the state of the thread changes
### Expected Function
### Notions
- [Trait std::ops::Drop](https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/std/ops/trait.Drop.html)
- [Struct std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)
- [Interior Mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html)
### Expected Functions
```rust
use std::cell::{RefCell, Cell};
@ -65,10 +74,11 @@ impl<'a> Thread<'a> {
### Usage
Here is a program to test your function
Here is a program to test your function,
```rust
use std::rc::Rc;
use drop_the_thread::*;
fn main() {
let worker = Workers::new();
@ -101,9 +111,3 @@ student@ubuntu:~/[[ROOT]]/test$ cargo run
(false, 2, Cell { value: 2 }, 1)
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/std/ops/trait.Drop.html
- https://doc.rust-lang.org/std/cell/struct.RefCell.html
- https://doc.rust-lang.org/book/ch15-05-interior-mutability.html

24
subjects/how_many_references/README.md

@ -2,14 +2,19 @@
### Instructions
Create the following functions :
Create the following **functions** :
- `add_ele` that adds an element to the value in the `Node`
- `how_many_references` that returns how many times the value is referenced in the code
- `rm_all_ref` that receives a `Rc<String>` and removes all elements from the vector that
- `add_ele` which adds an element to the value in the `Node`
- `how_many_references` which returns how many times the value is referenced in the code
- `rm_all_ref` which receives a `Rc<String>` and removes all elements from the vector that
are equal to that value, this should only happen if the two Rcs point to the same allocation
### Expected Function
### Notions
- [Reference Counted Smart Pointer](https://doc.rust-lang.org/book/ch15-04-rc.html)
- [Struct std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html)
### Expected Functions and structures
```rust
pub use std::rc::Rc;
@ -31,9 +36,11 @@ pub fn how_many_references(value: &Rc<String>) -> usize {}
### Usage
Here is a program to test your function
Here is a program to test your functions,
```rust
use how_many_references::*;
fn main() {
let a = Rc::new(String::from("a"));
let b = Rc::new(String::from("b"));
@ -71,8 +78,3 @@ b: 2
c: 2
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/book/ch15-04-rc.html
- https://doc.rust-lang.org/std/rc/struct.Rc.html

66
subjects/ref_cell/README.md

@ -2,14 +2,14 @@
### Instructions
### 1Âş part
#### First part (messenger.rs)
Create a module called `messenger`. This module will be able to inform a user of how much references of a given value he is using.
The main objective for this module is to limit how many times a value is referenced.
Create a module called `messenger`. This module will be able to inform a user of how many references of a given value he is using.
The main objective of this module is to limit how many times a value is referenced.
For the module you must create the following:
For this module the following must be created:
- A trait `Logger` that implements three functions: `warning`, `info`, `error`. All function should receive a reference to themselves and a string literal.
- A trait `Logger` which implements three functions: `warning`, `info`, `error`. All **functions** should receive a reference to themselves and a string literal.
```rust
fn warning(&self, msg: &str);
@ -17,7 +17,7 @@ For the module you must create the following:
fn error(&self, msg: &str);
```
- A structure called `Tracker`, that must have the fields: `logger` being a reference to the `Logger`, `value` being the count of how many times the value was referenced,
- A structure called `Tracker`, which must have the fields: `logger` being a reference to the `Logger`, `value` being the count of how many times the value was referenced,
`max` being the max count of references the actual value can achieve.
- An implementation of three functions that are associated to the `Tracker` structure:
@ -27,66 +27,71 @@ For the module you must create the following:
If the percentage is equal or greater to 70% of the limit usage, it should write **("Warning: you have used up over {}% of your quota! Proceeds with precaution", <calculated_percentage>)** to the `warning` function
- `peek` that will take a peek of how much usage the variable already has. It should write **("Info: you are using up too {}% of your quote", <calculated_percentage>)** to the `info` function
### 2ÂŞ part
### Second part (lib.rs)
Afterwards you must use the module `messenger` and create the following:
- A structure `Worker` that has the fields:
- `track_value` this will be the value that will be tracked by the tracker.
- `mapped_messages` that will have the latest messages. This must be a HashMap with the key being the type of message
sent by the logger (info, error or warning) and the value being the message
sent by the logger (info, error or warning) and the value being the message
- `all_messages` that will be a vector of all messages sent.
- A `new` function that initializes the structure `Worker`
- To use the trait `Logger` you must implement it for the Worker structure. Each function (warning, error and info) must insert the message to the
respective fields of the structure Worker.
You must use **interior mutability**, this means it must be able to mutate data even when there are immutable references to that data.
You must use **interior mutability**, this means it must be able to mutate data even when there are immutable references to that data. Consequently, the user will not need to use the keyword `mut` (tip: RefCell)
So the user doesn't need to use the keyword `mut` (tip: RefCell)
### Notions
- [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)
- [Struct std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html)
### Usage
Here is a program to test your function
Here is a program to test your function,
```rust
use ref_cell::*;
fn main() {
// initialize the worker
let Logger = Worker::new(1);
let logger = Worker::new(1);
// initialize the tracker, with the max number of
// called references as 10
let track = Tracker::new(&Logger, 10);
let track = Tracker::new(&logger, 10);
let _a = Logger.track_value.clone(); // |\
let _a1 = Logger.track_value.clone(); // | -> increase the Rc to 4 references
let _a2 = Logger.track_value.clone(); // |/
let _a = logger.track_value.clone(); // |\
let _a1 = logger.track_value.clone(); // | -> increase the Rc to 4 references
let _a2 = logger.track_value.clone(); // |/
// take a peek of how much we already used from our quota
track.peek(&Logger.track_value);
track.peek(&logger.track_value);
let _b = Logger.track_value.clone(); // |\
let _b1 = Logger.track_value.clone(); // | -> increase the Rc to 8 references
let _b2 = Logger.track_value.clone(); // | /
let _b3 = Logger.track_value.clone(); // |/
let _b = logger.track_value.clone(); // |\
let _b1 = logger.track_value.clone(); // | -> increase the Rc to 8 references
let _b2 = logger.track_value.clone(); // | /
let _b3 = logger.track_value.clone(); // |/
// this will set the value and making a verification of
// how much we already used of our quota
track.set_value(&Logger.track_value);
track.set_value(&logger.track_value);
let _c = Logger.track_value.clone(); // | -> increase the Rc to 9 references
let _c = logger.track_value.clone(); // | -> increase the Rc to 9 references
// this will set the value and making a verification of
// how much we already used of our quota
track.set_value(&Logger.track_value);
track.set_value(&logger.track_value);
let _c1 = Logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
let _c1 = logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
track.set_value(&Logger.track_value);
track.set_value(&logger.track_value);
for (k ,v) in Logger.mapped_messages.into_inner() {
for (k ,v) in logger.mapped_messages.into_inner() {
println!("{:?}", (k ,v));
}
println!("{:?}", Logger.all_messages.into_inner());
println!("{:?}", logger.all_messages.into_inner());
}
```
@ -105,8 +110,3 @@ student@ubuntu:~/[[ROOT]]/test$ cargo run
]
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/std/cell/struct.RefCell.html
- https://doc.rust-lang.org/std/rc/struct.Rc.html

Loading…
Cancel
Save