From e70d46f49a7af2576ad18926dd0d83cfef101250 Mon Sep 17 00:00:00 2001 From: lee Date: Mon, 28 Dec 2020 17:30:38 +0000 Subject: [PATCH] quest 8: adding tests and subjects --- rust/tests/project_motion_test/Cargo.lock | 12 ++ rust/tests/project_motion_test/Cargo.toml | 10 ++ rust/tests/project_motion_test/src/main.rs | 56 +++++++++ rust/tests/sales_test/Cargo.lock | 12 ++ rust/tests/sales_test/Cargo.toml | 10 ++ rust/tests/sales_test/src/main.rs | 133 +++++++++++++++++++++ subjects/project_motion/README.md | 70 +++++++++++ subjects/sales/README.md | 101 ++++++++++++++++ 8 files changed, 404 insertions(+) create mode 100644 rust/tests/project_motion_test/Cargo.lock create mode 100644 rust/tests/project_motion_test/Cargo.toml create mode 100644 rust/tests/project_motion_test/src/main.rs create mode 100644 rust/tests/sales_test/Cargo.lock create mode 100644 rust/tests/sales_test/Cargo.toml create mode 100644 rust/tests/sales_test/src/main.rs create mode 100644 subjects/project_motion/README.md create mode 100644 subjects/sales/README.md diff --git a/rust/tests/project_motion_test/Cargo.lock b/rust/tests/project_motion_test/Cargo.lock new file mode 100644 index 00000000..5e0f535f --- /dev/null +++ b/rust/tests/project_motion_test/Cargo.lock @@ -0,0 +1,12 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "project_motion" +version = "0.1.0" + +[[package]] +name = "project_motion_test" +version = "0.1.0" +dependencies = [ + "project_motion", +] diff --git a/rust/tests/project_motion_test/Cargo.toml b/rust/tests/project_motion_test/Cargo.toml new file mode 100644 index 00000000..b088cb33 --- /dev/null +++ b/rust/tests/project_motion_test/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "project_motion_test" +version = "0.1.0" +authors = ["lee "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +project_motion = { path = "../../../../rust-piscine-solutions/project_motion"} diff --git a/rust/tests/project_motion_test/src/main.rs b/rust/tests/project_motion_test/src/main.rs new file mode 100644 index 00000000..13d4c146 --- /dev/null +++ b/rust/tests/project_motion_test/src/main.rs @@ -0,0 +1,56 @@ +use project_motion::*; + +fn main() { + let mut obj = Object::throw_object(50.0, 150.0); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_short_distance() { + let mut object = Object::throw_object(50.0, 20.0); + + assert_eq!(object.next(), Some(Object { distance: 50.0, velocity: 50.0, height: 15.1, time: 1.0 })); + assert_eq!(object, Object { distance: 50.0, velocity: 50.0, height: 15.1, time: 1.0 }); + + assert!(object.next().is_none(), "{:?} instead of None", object); + assert!(object.next().is_none(), "{:?} instead of None", object); + } + + #[test] + fn test_media_distance() { + let mut object = Object::throw_object(100.0, 30.0); + + assert_eq!(object.next(), Some(Object { distance: 100.0, velocity: 100.0, height: 25.1, time: 1.0 })); + assert_eq!(object, Object { distance: 100.0, velocity: 100.0, height: 25.1, time: 1.0 }); + + assert_eq!(object.next(), Some(Object { distance: 200.0, velocity: 100.0, height: 5.5, time: 2.0 })); + assert_eq!(object, Object { distance: 200.0, velocity: 100.0, height: 5.5, time: 2.0 }); + + assert!(object.next().is_none(), "{:?} instead of None", object); + } + + #[test] + fn test_long_distance() { + let mut object = Object::throw_object(120.0, 100.0); + + assert_eq!(object.next(), Some(Object { distance: 120.0, velocity: 120.0, height: 95.1, time: 1.0 })); + assert_eq!(object, Object { distance: 120.0, velocity: 120.0, height: 95.1, time: 1.0 }); + + assert_eq!(object.next(), Some(Object { distance: 240.0, velocity: 120.0, height: 75.5, time: 2.0 })); + assert_eq!(object, Object { distance: 240.0, velocity: 120.0, height: 75.5, time: 2.0 }); + + assert_eq!(object.next(), Some(Object { distance: 360.0, velocity: 120.0, height: 31.4, time: 3.0 })); + assert_eq!(object, Object { distance: 360.0, velocity: 120.0, height: 31.4, time: 3.0 }); + + assert!(object.next().is_none(), "{:?} instead of None", object); + } +} diff --git a/rust/tests/sales_test/Cargo.lock b/rust/tests/sales_test/Cargo.lock new file mode 100644 index 00000000..b3dffd2f --- /dev/null +++ b/rust/tests/sales_test/Cargo.lock @@ -0,0 +1,12 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "sales" +version = "0.1.0" + +[[package]] +name = "sales_test" +version = "0.1.0" +dependencies = [ + "sales", +] diff --git a/rust/tests/sales_test/Cargo.toml b/rust/tests/sales_test/Cargo.toml new file mode 100644 index 00000000..42d70f49 --- /dev/null +++ b/rust/tests/sales_test/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "sales_test" +version = "0.1.0" +authors = ["lee "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +sales = { path = "../../../../rust-piscine-solutions/sales"} diff --git a/rust/tests/sales_test/src/main.rs b/rust/tests/sales_test/src/main.rs new file mode 100644 index 00000000..ded9b1d9 --- /dev/null +++ b/rust/tests/sales_test/src/main.rs @@ -0,0 +1,133 @@ +use sales::*; + +fn main() { + let store = Store::new(vec![ + (String::from("product A"), 1.23), + (String::from("product B"), 23.1), + (String::from("product C"), 3.12)]); + + println!("{:?}", store); + // output: + // Store { products: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)] } + + let mut cart = Cart::new(); + cart.insert_item(&store, String::from("product A")); + cart.insert_item(&store, String::from("product B")); + cart.insert_item(&store, String::from("product C")); + + println!("{:?}", cart.generate_receipt()); + // output: + // [1.17, 2.98, 22.07] + + println!("{:?}", cart); + // output: + // Cart { items: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)], receipt: [1.17, 2.98, 22.07] } +} +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug)] + struct Tests { + store: Store, + carts: Vec<(Cart, Vec)>, + } + + fn add_items(s: &Store, items: Vec<&str>, c: &mut Cart) { + for item in items.iter() { + c.insert_item(s, item.to_string()); + } + } + + impl Tests { + fn new() -> Tests { + let store = Store::new(vec![ + (String::from("product A"), 1.23), + (String::from("product B"), 23.1), + (String::from("product C"), 3.12), + (String::from("product D"), 9.75), + (String::from("product E"), 1.75), + (String::from("product F"), 23.75), + (String::from("product G"), 2.75), + (String::from("product H"), 1.64), + (String::from("product I"), 15.23), + (String::from("product J"), 2.10), + (String::from("product K"), 54.91), + (String::from("product L"), 43.99), + ]); + + let mut c = Cart::new(); + let mut c1 = Cart::new(); + let mut c2 = Cart::new(); + let mut c3 = Cart::new(); + add_items(&store, vec!["product A", "product B", "product C"], &mut c); + let sol = vec![1.17, 2.98, 22.07]; + add_items( + &store, + vec![ + "product A", + "product B", + "product C", + "product D", + "product E", + "product F", + "product G", + ], + &mut c1, + ); + let sol1 = vec![1.17, 1.67, 2.62, 2.98, 9.31, 22.05, 22.67]; + add_items( + &store, + vec![ + "product A", + "product B", + "product C", + "product D", + "product E", + "product F", + "product G", + "product H", + "product I", + ], + &mut c2, + ); + let sol2 = vec![1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]; + add_items( + &store, + vec![ + "product A", + "product B", + "product C", + "product D", + "product E", + "product F", + "product G", + "product H", + "product I", + "product J", + "product K", + "product L", + ], + &mut c3, + ); + let sol3 = vec![ + 1.18, 1.58, 1.69, 2.02, 2.65, 3.01, 9.39, 14.67, 22.25, 22.88, 42.38, 52.89, + ]; + + Tests { + store, + carts: vec![(c, sol), (c1, sol1), (c2, sol2), (c3, sol3)], + } + } + } + + #[test] + fn test_generate_receipt() { + let cases = Tests::new(); + + for (mut c, sol) in cases.carts.into_iter() { + assert_eq!(c.generate_receipt(), sol); + assert_eq!(c.receipt, sol); + } + } +} diff --git a/subjects/project_motion/README.md b/subjects/project_motion/README.md new file mode 100644 index 00000000..dbf21ae2 --- /dev/null +++ b/subjects/project_motion/README.md @@ -0,0 +1,70 @@ +## project_motion + +### Instructions + +For this exercise you will have to create a [projectile motion](https://cimg2.ck12.org/datastreams/f-d%3Abb024be6673110b31e78b46819e792adaed8dc661e082a61f0a6d64e%2BIMAGE%2BIMAGE.1). + +You will be provided with a structure called `Object` that will have all variables that are +essential for the projectile physics. (distance, velocity, height, time) + +You must implement : + +- A function `throw_object` that will initialize the Object with a given velocity and height. +- The trait Iterator with the `.next()` in which it must calculate the next position of the object after 1 second. + It will return an `Option` with the Object, It will return `None` if the object already reached the floor. + +### Expected Function + +```rust + +#[derive(Debug, Clone, PartialEq)] +pub struct Object { + pub distance: f32, + pub velocity: f32, + pub height: f32, + pub time: f32, +} + +impl Object { + pub fn throw_object(velocity: f32, height: f32) -> Object {} +} + +impl Iterator for Object { + // next +} + +``` + +### Usage + +Here is a program to test your function + +```rust +fn main() { + let mut obj = Object::throw_object(50.0, 150.0); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); + println!("{:?}", obj.next()); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +Some(Object { distance: 50.0, velocity: 50.0, height: 145.1, time: 1.0 }) +Some(Object { distance: 100.0, velocity: 50.0, height: 125.5, time: 2.0 }) +Some(Object { distance: 150.0, velocity: 50.0, height: 81.4, time: 3.0 }) +Some(Object { distance: 200.0, velocity: 50.0, height: 3.0, time: 4.0 }) +None +None +student@ubuntu:~/[[ROOT]]/test$ +``` + +### Notions + +- https://doc.rust-lang.org/std/iter/trait.Iterator.html +- https://doc.rust-lang.org/rust-by-example/trait/iter.html diff --git a/subjects/sales/README.md b/subjects/sales/README.md new file mode 100644 index 00000000..477e5f59 --- /dev/null +++ b/subjects/sales/README.md @@ -0,0 +1,101 @@ +## sales + +### Instructions + +You will have to create a shopping system, where you will have a : + +- Store that will save all the products in it +- Cart that will have `items`, that the client will buy, and a `receipt` + +This store is having a promotion, "Buy three and get one for free" (the free item must be the cheapest). The receipt must not present +any value as 0, so you will have to apply the promotion to all items instead. + +### Expected Function + +```rust + +#[derive(Debug, Clone)] +pub struct Store { + pub products: Vec<(String, f32)>, +} +impl Store { + pub fn new(products: Vec<(String, f32)>) -> Store { + Store { products } + } +} + +#[derive(Debug, Clone)] +pub struct Cart { + // expected public fields +} +impl Cart { + pub fn new() -> Cart {} + pub fn insert_item(&mut self, s: &Store, ele: String) {} + pub fn get_prices(&self) -> Vec {} + pub fn generate_receipt(&mut self) -> Vec {} +} + +``` + +### Example + +`[1.23, 3.12, 23.1]` -> receipt will be `[1.17, 2.98, 22.07]` + +So `1.17 + 2.98 + 22.07 == 3.12 + 23.1 + 0` + +This is a percentage calculation, and it can be applied to a set of three items. +If the client purchase 9 items it will be applied the promotion, three for free, to all items + +|--------------| |---------------| |---------------| +`[1.23, 23.1, 3.12, 9.75, 1.75, 23.75, 2.75, 1.64, 15.23]` -> receipt will be `[1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]` + +|--------| |--------| |--------| +`[3.12, 9.75, 1.75, 23.75, 2.75, 1.64, 15.23]` -> receipt will be `[1.54, 1.65, 2.59, 2.94, 9.18, 14.34, 22.36]` + +and so on... (hint: Closures is the way) + +You will have to implement for the Cart structure the following function: + +- `new`, that will initialize the cart +- `insert_item`, that will receive a reference to `Store` and a `String`. Just like the name says you will + have to insert the item to the cart +- `generate_receipt`, that returns a vector of sorted floats. This function must generate the receipt just +like the example above, using the promotion. Also saving the result in the filed `receipt`. + +### Usage + +Here is a program to test your function + +```rust +fn main() { + let store = Store::new(vec![ + (String::from("product A"), 1.23), + (String::from("product B"), 23.1), + (String::from("product C"), 3.12)]); + + println!("{:?}", store); + + let mut cart = Cart::new(); + cart.insert_item(&store, String::from("product A")); + cart.insert_item(&store, String::from("product B")); + cart.insert_item(&store, String::from("product C")); + + println!("{:?}", cart.generate_receipt()); + + println!("{:?}", cart); +} +``` + +And its output: + +```console +student@ubuntu:~/[[ROOT]]/test$ cargo run +Store { products: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)] } +[1.17, 2.98, 22.07] +Cart { items: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)], receipt: [1.17, 2.98, 22.07] } +student@ubuntu:~/[[ROOT]]/test$ +``` + +### Notions + +- https://doc.rust-lang.org/rust-by-example/fn/closures.html