diff --git a/.gitignore b/.gitignore deleted file mode 100644 index c41cc9e3..00000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index dbea45eb..d4f4ba07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,14 @@ version = "0.1.0" name = "complex-type" version = "0.1.0" +[[package]] +name = "generic-type" +version = "0.1.0" + [[package]] name = "ownership-borrowing" version = "0.1.0" + +[[package]] +name = "traits" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 3f7870cb..a6b5590a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ members = [ "./exercises/basic-of-rust", "./exercises/ownership-borrowing", "./exercises/complex-type", + "./exercises/generic-type", + "./exercises/traits", ] @@ -33,5 +35,13 @@ path = "./exercises/complex-type/src/structs.rs" name = "enums" path = "./exercises/complex-type/src/enums.rs" +[[test]] +name = "generic-type" +path = "./exercises/generic-type/src/lib.rs" + +[[test]] +name = "traits" +path = "./exercises/traits/src/lib.rs" + [dependencies] \ No newline at end of file diff --git a/exercises/generic-type/Cargo.toml b/exercises/generic-type/Cargo.toml new file mode 100644 index 00000000..b8eac90e --- /dev/null +++ b/exercises/generic-type/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "generic-type" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] \ No newline at end of file diff --git a/exercises/generic-type/README.md b/exercises/generic-type/README.md new file mode 100644 index 00000000..9f9caeee --- /dev/null +++ b/exercises/generic-type/README.md @@ -0,0 +1,4 @@ +## Complete Generic type exercises +### Generic type + ++ Make it compile, add logic code `Generic Type` exercises in `exercises/generic-type/src/lib.rs` diff --git a/exercises/generic-type/src/lib.rs b/exercises/generic-type/src/lib.rs new file mode 100644 index 00000000..da43a64c --- /dev/null +++ b/exercises/generic-type/src/lib.rs @@ -0,0 +1,147 @@ +// Exercise 1 +// Implement struct Point to make it work. +// Make it compile +fn exercise1() { + let integer = Position { x: 5, y: 10 }; + let float = Position { x: 1.0, y: 4.0 }; +} +struct Position { + x: T, + y: T, +} + + +// Exercise 2 +// Modify this struct to make the code work +// Make it compile +struct Point { + x: T, + y: U, +} + +fn exercise2() { + // DON'T modify this code. + let p = Point{x: 5, y : "hello".to_string()}; +} + + + +// Exercise 3 +// Make it compile +// Add generic for Val to make the code work, DON'T modify the code in `main`. +struct Val{ + val: T, +} + +implVal{ + fn value(&self) -> &T{ + &self.val + } +} + + +fn exercise3() { + let x = Val{ val: 3.0 }; + let y = Val{ val: "hello".to_string()}; + println!("{}, {}", x.value(), y.value()); +} + +// Exercise 4 +// Find the maximum value in a collection +// Make it compile +// Implementing logic +// Run tests + +fn find_max(collection: &[T]) -> Option<&T> { + collection.iter().max() +} + +// Exercise 5 +// Reverse the elements in a collection +// Make it compile +// Run tests +fn reverse_collection(collection: &mut [T]) { + collection.reverse(); +} + + +// Exercise 6 +// Function to check if a collection contains a specific value +fn contains_value(collection: &[T], value: &T) -> bool { + collection.contains(value) +} + +// Unit tests +#[cfg(test)] +mod tests { + use super::*; + + // Test for exercise 4 + #[test] + fn test_find_max_with_numbers() { + let numbers = vec![1, 5, 3, 8, 2]; + assert_eq!(find_max(&numbers), Some(&8)); + } + + // Test for exercise 4 + #[test] + fn test_find_max_with_strings() { + let strings = vec!["apple", "banana", "cherry", "durian"]; + assert_eq!(find_max(&strings), Some(&"durian")); + } + + // Test for exercise 4 + #[test] + fn test_find_max_with_empty_collection() { + let empty: Vec = Vec::new(); + assert_eq!(find_max(&empty), None); + } + + // Test for exercise 5 + #[test] + fn test_reverse_collection_with_numbers() { + let mut numbers = vec![1, 2, 3, 4, 5]; + reverse_collection(&mut numbers); + assert_eq!(numbers, vec![5, 4, 3, 2, 1]); + } + + // Test for exercise 5 + #[test] + fn test_reverse_collection_with_strings() { + let mut strings = vec!["apple", "banana", "cherry", "durian"]; + reverse_collection(&mut strings); + assert_eq!(strings, vec!["durian", "cherry", "banana", "apple"]); + } + + // Test for exercise 5 + #[test] + fn test_reverse_collection_with_empty_collection() { + let mut empty: Vec = Vec::new(); + reverse_collection(&mut empty); + assert_eq!(empty, Vec::::new()); + } + + // Test for exercise 6 + #[test] + fn test_contains_value_with_numbers() { + let numbers = vec![1, 2, 3, 4, 5]; + assert_eq!(contains_value(&numbers, &3), true); + assert_eq!(contains_value(&numbers, &6), false); + } + + // Test for exercise 6 + #[test] + fn test_contains_value_with_strings() { + let strings = vec!["apple", "banana", "cherry", "durian"]; + assert_eq!(contains_value(&strings, &"banana"), true); + assert_eq!(contains_value(&strings, &"grape"), false); + } + + // Test for exercise 6 + #[test] + fn test_contains_value_with_empty_collection() { + let empty: Vec = Vec::new(); + assert_eq!(contains_value(&empty, &5), false); + } + +} \ No newline at end of file diff --git a/exercises/traits/Cargo.toml b/exercises/traits/Cargo.toml new file mode 100644 index 00000000..3f82b28c --- /dev/null +++ b/exercises/traits/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "traits" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] \ No newline at end of file diff --git a/exercises/traits/README.md b/exercises/traits/README.md new file mode 100644 index 00000000..f87c4b5c --- /dev/null +++ b/exercises/traits/README.md @@ -0,0 +1,10 @@ +## Complete Trait exercises +### Trait + ++ Make it compile and Complete `Traits` exercises in `exercises/traits/src/lib.rs` + ++ Run tests to check your implementation + +``` + cargo test --test traits +``` \ No newline at end of file diff --git a/exercises/traits/src/lib.rs b/exercises/traits/src/lib.rs new file mode 100644 index 00000000..f9baeca5 --- /dev/null +++ b/exercises/traits/src/lib.rs @@ -0,0 +1,221 @@ +// Exercise 1 +// Fill in the two impl blocks to make the code work. +// Make it compile +// Run tests +trait Hello { + fn say_hi(&self) -> String { + String::from("hi") + } + + fn say_something(&self) -> String; +} + +//TODO +struct Student {} +impl Hello for Student { + fn say_hi(&self) -> String { + String::from("hi") + } + fn say_something(&self) -> String { + String::from("I'm a good student") + } +} +//TODO +struct Teacher {} +impl Hello for Teacher { + fn say_hi(&self) -> String { + String::from("Hi, I'm your new teacher") + } + fn say_something(&self) -> String { + String::from("I'm not a bad teacher") + } +} + + +// Exercise 2 +// Make it compile in unit test for exercise 2 +// Hint: use #[derive] for struct Point +// Run tests +#[derive(PartialEq, Eq, Debug)] +struct Point { + x: i32, + y: i32, +} + + +// Exercise 3 +// Make it compile +// Implement `fn sum` with trait bound in two ways. +// Run tests +// Hint: Trait Bound +// First way: fn sum +use std::ops::Add; + +fn sum(x: T, y: T) -> T +where + T: Add, +{ + x + y +} + +// Second way: fn sum_2 +fn sum_2>(x: T, y: T) -> T { + x + y +} + + +// Exercise 4 +// Fix errors and implement +// Hint: Static Dispatch and Dynamic Dispatch +// Run tests +trait Foo { + fn method(&self) -> String; +} + +impl Foo for u8 { + fn method(&self) -> String { format!("u8: {}", *self) } +} + +impl Foo for String { + fn method(&self) -> String { format!("string: {}", *self) } +} + +// IMPLEMENT below with generics and parameters +fn static_dispatch(x: T) -> String { + x.method() +} + +// Implement below with trait objects and parameters +fn dynamic_dispatch(x: &dyn Foo) -> String { + x.method() +} + +// Exercise 5 +// Fix errors and fill in the blanks +// Run tests +// Hint: &dyn and Box +trait Draw { + fn draw(&self) -> String; +} + +impl Draw for u8 { + fn draw(&self) -> String { + format!("u8: {}", *self) + } +} + +impl Draw for f64 { + fn draw(&self) -> String { + format!("f64: {}", *self) + } +} + +fn draw_with_box(x: Box) { + x.draw(); +} + +fn draw_with_ref(x: &dyn Draw) { + x.draw(); +} + +// Exercise 6 +// Fix errors and implement +// Run tests +// Hint: Associated Type + +trait Container { + type Item; + fn insert(&mut self, item: Self::Item); + fn remove(&mut self) -> Option; + fn is_empty(&self) -> bool; +} + +struct Stack { + items: Vec, +} + +//TODO implement Container for Stack +impl Container for Stack { + type Item = T; + fn insert(&mut self, item: Self::Item) { + self.items.push(item); + } + fn remove(&mut self) -> Option { + self.items.pop() + } + fn is_empty(&self) -> bool { + self.items.is_empty() + } +} + + + +#[cfg(test)] +mod tests { + use super::*; + + // Test for exercise 2 + + #[test] + fn exercise1_should_work() { + let s = Student {}; + assert_eq!(s.say_hi(), "hi"); + assert_eq!(s.say_something(), "I'm a good student"); + + let t = Teacher {}; + assert_eq!(t.say_hi(), "Hi, I'm your new teacher"); + assert_eq!(t.say_something(), "I'm not a bad teacher"); + } + + #[test] + fn exercise2_should_work() { + let point1 = Point { x: 1, y: 2 }; + let point2 = Point { x: 1, y: 2 }; + let point3 = Point { x: 3, y: 4 }; + + assert_eq!(point1, point2); + assert_ne!(point1, point3); + } + + #[test] + fn exercise3_should_work() { + assert_eq!(sum(1, 2), 3); + } + + #[test] + fn exercise4_should_work() { + let x = 5u8; + let y = "Hello".to_string(); + + static_dispatch(x); + dynamic_dispatch(&y); + } + + #[test] + fn exercise5_should_work() { + let x = 1.1f64; + let y = 8u8; + + // Draw x. + draw_with_box(Box::new(x)); + + // Draw y. + draw_with_ref(&y); + } + + #[test] + fn exercise6_should_work(){ + let mut stack: Stack = Stack { items: Vec::new() }; + assert!(stack.is_empty()); + stack.insert(1); + stack.insert(2); + stack.insert(3); + assert!(!stack.is_empty()); + assert_eq!(stack.remove(), Some(3)); + assert_eq!(stack.remove(), Some(2)); + assert_eq!(stack.remove(), Some(1)); + assert_eq!(stack.remove(), None); + assert!(stack.is_empty()); + } + +} \ No newline at end of file