diff options
| author | Hunter Kvalevog <hunter@kvog.sh> | 2026-10-02 21:53:51 -0500 |
|---|---|---|
| committer | Hunter Kvalevog <hunter@kvog.sh> | 2026-10-02 21:53:51 -0500 |
| commit | 4dfc11d74ab02ac5765ae5d08fb750c91f4744b4 (patch) | |
| tree | 17ba62056d6b691dd0217b0e8f1b3a5826dce0f6 /rustlings/solutions | |
| parent | 02d8f1c62896576e1266553a56980eddbc2a88d7 (diff) | |
rustlings: move to rust/
Diffstat (limited to 'rustlings/solutions')
95 files changed, 0 insertions, 2966 deletions
diff --git a/rustlings/solutions/00_intro/intro1.rs b/rustlings/solutions/00_intro/intro1.rs deleted file mode 100644 index 4fe8454..0000000 --- a/rustlings/solutions/00_intro/intro1.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - // Congratulations, you finished the first exercise 🎉 - // As an introduction to Rustlings, the first exercise only required - // entering `n` in the terminal to go to the next exercise. -} diff --git a/rustlings/solutions/00_intro/intro2.rs b/rustlings/solutions/00_intro/intro2.rs deleted file mode 100644 index b8e031a..0000000 --- a/rustlings/solutions/00_intro/intro2.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // `println!` instead of `printline!`. - println!("Hello world!"); -} diff --git a/rustlings/solutions/01_variables/variables1.rs b/rustlings/solutions/01_variables/variables1.rs deleted file mode 100644 index 58d046b..0000000 --- a/rustlings/solutions/01_variables/variables1.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - // Declaring variables requires the `let` keyword. - let x = 5; - - println!("x has the value {x}"); -} diff --git a/rustlings/solutions/01_variables/variables2.rs b/rustlings/solutions/01_variables/variables2.rs deleted file mode 100644 index 50b8d1b..0000000 --- a/rustlings/solutions/01_variables/variables2.rs +++ /dev/null @@ -1,16 +0,0 @@ -fn main() { - // The easiest way to fix the compiler error is to initialize the - // variable `x`. By setting its value to an integer, Rust infers its type - // as `i32` which is the default type for integers. - let x = 42; - - // But we can enforce a type different from the default `i32` by adding - // a type annotation: - // let x: u8 = 42; - - if x == 10 { - println!("x is ten!"); - } else { - println!("x is not ten!"); - } -} diff --git a/rustlings/solutions/01_variables/variables3.rs b/rustlings/solutions/01_variables/variables3.rs deleted file mode 100644 index 15f6557..0000000 --- a/rustlings/solutions/01_variables/variables3.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![allow(clippy::needless_late_init)] - -fn main() { - // Reading uninitialized variables isn't allowed in Rust! - // Therefore, we need to assign a value first. - let x: i32 = 42; - - println!("Number {x}"); - - // It is possible to declare a variable and initialize it later. - // But it can't be used before initialization. - let y: i32; - y = 42; - println!("Number {y}"); -} diff --git a/rustlings/solutions/01_variables/variables4.rs b/rustlings/solutions/01_variables/variables4.rs deleted file mode 100644 index 7de6bcb..0000000 --- a/rustlings/solutions/01_variables/variables4.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - // In Rust, variables are immutable by default. - // Adding the `mut` keyword after `let` makes the declared variable mutable. - let mut x = 3; - println!("Number {x}"); - - x = 5; - println!("Number {x}"); -} diff --git a/rustlings/solutions/01_variables/variables5.rs b/rustlings/solutions/01_variables/variables5.rs deleted file mode 100644 index 0ea3903..0000000 --- a/rustlings/solutions/01_variables/variables5.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - let number = "T-H-R-E-E"; - println!("Spell a number: {number}"); - - // Using variable shadowing - // https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#shadowing - let number = 3; - println!("Number plus two is: {}", number + 2); -} diff --git a/rustlings/solutions/01_variables/variables6.rs b/rustlings/solutions/01_variables/variables6.rs deleted file mode 100644 index 25b7a1e..0000000 --- a/rustlings/solutions/01_variables/variables6.rs +++ /dev/null @@ -1,6 +0,0 @@ -// The type of constants must always be annotated. -const NUMBER: u64 = 3; - -fn main() { - println!("Number: {NUMBER}"); -} diff --git a/rustlings/solutions/02_functions/functions1.rs b/rustlings/solutions/02_functions/functions1.rs deleted file mode 100644 index dc52744..0000000 --- a/rustlings/solutions/02_functions/functions1.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Some function with the name `call_me` without arguments or a return value. -fn call_me() { - println!("Hello world!"); -} - -fn main() { - call_me(); -} diff --git a/rustlings/solutions/02_functions/functions2.rs b/rustlings/solutions/02_functions/functions2.rs deleted file mode 100644 index f14ffa3..0000000 --- a/rustlings/solutions/02_functions/functions2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// The type of function arguments must be annotated. -// Added the type annotation `u64`. -fn call_me(num: u64) { - for i in 0..num { - println!("Ring! Call number {}", i + 1); - } -} - -fn main() { - call_me(3); -} diff --git a/rustlings/solutions/02_functions/functions3.rs b/rustlings/solutions/02_functions/functions3.rs deleted file mode 100644 index ce5fe8e..0000000 --- a/rustlings/solutions/02_functions/functions3.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn call_me(num: u8) { - for i in 0..num { - println!("Ring! Call number {}", i + 1); - } -} - -fn main() { - // `call_me` expects an argument. - call_me(5); -} diff --git a/rustlings/solutions/02_functions/functions4.rs b/rustlings/solutions/02_functions/functions4.rs deleted file mode 100644 index f823de2..0000000 --- a/rustlings/solutions/02_functions/functions4.rs +++ /dev/null @@ -1,17 +0,0 @@ -fn is_even(num: i64) -> bool { - num % 2 == 0 -} - -// The return type must always be annotated. -fn sale_price(price: i64) -> i64 { - if is_even(price) { - price - 10 - } else { - price - 3 - } -} - -fn main() { - let original_price = 51; - println!("Your sale price is {}", sale_price(original_price)); -} diff --git a/rustlings/solutions/02_functions/functions5.rs b/rustlings/solutions/02_functions/functions5.rs deleted file mode 100644 index 677f327..0000000 --- a/rustlings/solutions/02_functions/functions5.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn square(num: i32) -> i32 { - // Removed the semicolon `;` at the end of the line below to implicitly return the result. - num * num -} - -fn main() { - let answer = square(3); - println!("The square of 3 is {answer}"); -} diff --git a/rustlings/solutions/03_if/if1.rs b/rustlings/solutions/03_if/if1.rs deleted file mode 100644 index 8512a60..0000000 --- a/rustlings/solutions/03_if/if1.rs +++ /dev/null @@ -1,28 +0,0 @@ -fn bigger(a: i32, b: i32) -> i32 { - if a > b { a } else { b } -} - -fn main() { - // You can optionally experiment here. -} - -// Don't mind this for now :) -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn ten_is_bigger_than_eight() { - assert_eq!(10, bigger(10, 8)); - } - - #[test] - fn fortytwo_is_bigger_than_thirtytwo() { - assert_eq!(42, bigger(32, 42)); - } - - #[test] - fn equal_numbers() { - assert_eq!(42, bigger(42, 42)); - } -} diff --git a/rustlings/solutions/03_if/if2.rs b/rustlings/solutions/03_if/if2.rs deleted file mode 100644 index 21c0dcd..0000000 --- a/rustlings/solutions/03_if/if2.rs +++ /dev/null @@ -1,35 +0,0 @@ -fn picky_eater(food: &str) -> &str { - if food == "strawberry" { - "Yummy!" - } else if food == "potato" { - "I guess I can eat that." - } else { - "No thanks!" - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn yummy_food() { - assert_eq!(picky_eater("strawberry"), "Yummy!"); - } - - #[test] - fn neutral_food() { - assert_eq!(picky_eater("potato"), "I guess I can eat that."); - } - - #[test] - fn default_disliked_food() { - assert_eq!(picky_eater("broccoli"), "No thanks!"); - assert_eq!(picky_eater("gummy bears"), "No thanks!"); - assert_eq!(picky_eater("literally anything"), "No thanks!"); - } -} diff --git a/rustlings/solutions/03_if/if3.rs b/rustlings/solutions/03_if/if3.rs deleted file mode 100644 index 571644d..0000000 --- a/rustlings/solutions/03_if/if3.rs +++ /dev/null @@ -1,53 +0,0 @@ -fn animal_habitat(animal: &str) -> &str { - let identifier = if animal == "crab" { - 1 - } else if animal == "gopher" { - 2 - } else if animal == "snake" { - 3 - } else { - // Any unused identifier. - 4 - }; - - // Instead of such an identifier, you would use an enum in Rust. - // But we didn't get into enums yet. - if identifier == 1 { - "Beach" - } else if identifier == 2 { - "Burrow" - } else if identifier == 3 { - "Desert" - } else { - "Unknown" - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn gopher_lives_in_burrow() { - assert_eq!(animal_habitat("gopher"), "Burrow") - } - - #[test] - fn snake_lives_in_desert() { - assert_eq!(animal_habitat("snake"), "Desert") - } - - #[test] - fn crab_lives_on_beach() { - assert_eq!(animal_habitat("crab"), "Beach") - } - - #[test] - fn unknown_animal() { - assert_eq!(animal_habitat("dinosaur"), "Unknown") - } -} diff --git a/rustlings/solutions/04_primitive_types/primitive_types1.rs b/rustlings/solutions/04_primitive_types/primitive_types1.rs deleted file mode 100644 index fac6ec0..0000000 --- a/rustlings/solutions/04_primitive_types/primitive_types1.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - let is_morning = true; - if is_morning { - println!("Good morning!"); - } - - let is_evening = !is_morning; - if is_evening { - println!("Good evening!"); - } -} diff --git a/rustlings/solutions/04_primitive_types/primitive_types2.rs b/rustlings/solutions/04_primitive_types/primitive_types2.rs deleted file mode 100644 index eecc680..0000000 --- a/rustlings/solutions/04_primitive_types/primitive_types2.rs +++ /dev/null @@ -1,21 +0,0 @@ -fn main() { - let my_first_initial = 'C'; - if my_first_initial.is_alphabetic() { - println!("Alphabetical!"); - } else if my_first_initial.is_numeric() { - println!("Numerical!"); - } else { - println!("Neither alphabetic nor numeric!"); - } - - // Example with an emoji. - let your_character = '🦀'; - - if your_character.is_alphabetic() { - println!("Alphabetical!"); - } else if your_character.is_numeric() { - println!("Numerical!"); - } else { - println!("Neither alphabetic nor numeric!"); - } -} diff --git a/rustlings/solutions/04_primitive_types/primitive_types3.rs b/rustlings/solutions/04_primitive_types/primitive_types3.rs deleted file mode 100644 index 8dd109f..0000000 --- a/rustlings/solutions/04_primitive_types/primitive_types3.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn main() { - // An array with 100 elements of the value 42. - let a = [42; 100]; - - if a.len() >= 100 { - println!("Wow, that's a big array!"); - } else { - println!("Meh, I eat arrays like that for breakfast."); - panic!("Array not big enough, more elements needed"); - } -} diff --git a/rustlings/solutions/04_primitive_types/primitive_types4.rs b/rustlings/solutions/04_primitive_types/primitive_types4.rs deleted file mode 100644 index 4807e66..0000000 --- a/rustlings/solutions/04_primitive_types/primitive_types4.rs +++ /dev/null @@ -1,23 +0,0 @@ -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - #[test] - fn slice_out_of_array() { - let a = [1, 2, 3, 4, 5]; - // 0 1 2 3 4 <- indices - // ------- - // | - // +--- slice - - // Note that the upper index 4 is excluded. - let nice_slice = &a[1..4]; - assert_eq!([2, 3, 4], nice_slice); - - // The upper index can be included by using the syntax `..=` (with `=` sign) - let nice_slice = &a[1..=3]; - assert_eq!([2, 3, 4], nice_slice); - } -} diff --git a/rustlings/solutions/04_primitive_types/primitive_types5.rs b/rustlings/solutions/04_primitive_types/primitive_types5.rs deleted file mode 100644 index 46d7ae8..0000000 --- a/rustlings/solutions/04_primitive_types/primitive_types5.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn main() { - let cat = ("Furry McFurson", 3.5); - - // Destructuring the tuple. - let (name, age) = cat; - - println!("{name} is {age} years old"); -} diff --git a/rustlings/solutions/04_primitive_types/primitive_types6.rs b/rustlings/solutions/04_primitive_types/primitive_types6.rs deleted file mode 100644 index 9b7c277..0000000 --- a/rustlings/solutions/04_primitive_types/primitive_types6.rs +++ /dev/null @@ -1,16 +0,0 @@ -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - #[test] - fn indexing_tuple() { - let numbers = (1, 2, 3); - - // Tuple indexing syntax. - let second = numbers.1; - - assert_eq!(second, 2, "This is not the 2nd number in the tuple!"); - } -} diff --git a/rustlings/solutions/05_vecs/vecs1.rs b/rustlings/solutions/05_vecs/vecs1.rs deleted file mode 100644 index 55b5676..0000000 --- a/rustlings/solutions/05_vecs/vecs1.rs +++ /dev/null @@ -1,23 +0,0 @@ -fn array_and_vec() -> ([i32; 4], Vec<i32>) { - let a = [10, 20, 30, 40]; // Array - - // Used the `vec!` macro. - let v = vec![10, 20, 30, 40]; - - (a, v) -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_array_and_vec_similarity() { - let (a, v) = array_and_vec(); - assert_eq!(a, *v); - } -} diff --git a/rustlings/solutions/05_vecs/vecs2.rs b/rustlings/solutions/05_vecs/vecs2.rs deleted file mode 100644 index 87f7625..0000000 --- a/rustlings/solutions/05_vecs/vecs2.rs +++ /dev/null @@ -1,55 +0,0 @@ -fn vec_loop(input: &[i32]) -> Vec<i32> { - let mut output = Vec::new(); - - for element in input { - output.push(2 * element); - } - - output -} - -fn vec_map_example(input: &[i32]) -> Vec<i32> { - // An example of collecting a vector after mapping. - // We map each element of the `input` slice to its value plus 1. - // If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`. - input.iter().map(|element| element + 1).collect() -} - -fn vec_map(input: &[i32]) -> Vec<i32> { - // We will dive deeper into iterators, but for now, this is all what you - // had to do! - // Advanced note: This method is more efficient because it automatically - // preallocates enough capacity. This can be done manually in `vec_loop` - // using `Vec::with_capacity(input.len())` instead of `Vec::new()`. - input.iter().map(|element| 2 * element).collect() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_vec_loop() { - let input = [2, 4, 6, 8, 10]; - let ans = vec_loop(&input); - assert_eq!(ans, [4, 8, 12, 16, 20]); - } - - #[test] - fn test_vec_map_example() { - let input = [1, 2, 3]; - let ans = vec_map_example(&input); - assert_eq!(ans, [2, 3, 4]); - } - - #[test] - fn test_vec_map() { - let input = [2, 4, 6, 8, 10]; - let ans = vec_map(&input); - assert_eq!(ans, [4, 8, 12, 16, 20]); - } -} diff --git a/rustlings/solutions/06_move_semantics/move_semantics1.rs b/rustlings/solutions/06_move_semantics/move_semantics1.rs deleted file mode 100644 index ac34e7a..0000000 --- a/rustlings/solutions/06_move_semantics/move_semantics1.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn fill_vec(vec: Vec<i32>) -> Vec<i32> { - let mut vec = vec; - // ^^^ added - - vec.push(88); - - vec -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn move_semantics1() { - let vec0 = vec![22, 44, 66]; - let vec1 = fill_vec(vec0); - // `vec0` can't be accessed anymore because it is moved to `fill_vec`. - assert_eq!(vec1, vec![22, 44, 66, 88]); - } -} diff --git a/rustlings/solutions/06_move_semantics/move_semantics2.rs b/rustlings/solutions/06_move_semantics/move_semantics2.rs deleted file mode 100644 index 7bcd33a..0000000 --- a/rustlings/solutions/06_move_semantics/move_semantics2.rs +++ /dev/null @@ -1,28 +0,0 @@ -fn fill_vec(vec: Vec<i32>) -> Vec<i32> { - let mut vec = vec; - - vec.push(88); - - vec -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn move_semantics2() { - let vec0 = vec![22, 44, 66]; - - // Cloning `vec0` so that the clone is moved into `fill_vec`, not `vec0` - // itself. - let vec1 = fill_vec(vec0.clone()); - - assert_eq!(vec0, [22, 44, 66]); - assert_eq!(vec1, [22, 44, 66, 88]); - } -} diff --git a/rustlings/solutions/06_move_semantics/move_semantics3.rs b/rustlings/solutions/06_move_semantics/move_semantics3.rs deleted file mode 100644 index 7ba4006..0000000 --- a/rustlings/solutions/06_move_semantics/move_semantics3.rs +++ /dev/null @@ -1,22 +0,0 @@ -fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> { - // ^^^ added - vec.push(88); - - vec -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn move_semantics3() { - let vec0 = vec![22, 44, 66]; - let vec1 = fill_vec(vec0); - assert_eq!(vec1, [22, 44, 66, 88]); - } -} diff --git a/rustlings/solutions/06_move_semantics/move_semantics4.rs b/rustlings/solutions/06_move_semantics/move_semantics4.rs deleted file mode 100644 index 1a39d4f..0000000 --- a/rustlings/solutions/06_move_semantics/move_semantics4.rs +++ /dev/null @@ -1,19 +0,0 @@ -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - #[test] - fn move_semantics4() { - let mut x = Vec::new(); - let y = &mut x; - // `y` used here. - y.push(42); - // The mutable reference `y` is not used anymore, - // therefore a new reference can be created. - let z = &mut x; - z.push(13); - assert_eq!(x, [42, 13]); - } -} diff --git a/rustlings/solutions/06_move_semantics/move_semantics5.rs b/rustlings/solutions/06_move_semantics/move_semantics5.rs deleted file mode 100644 index 1410e91..0000000 --- a/rustlings/solutions/06_move_semantics/move_semantics5.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![allow(clippy::ptr_arg)] - -// Borrows instead of taking ownership. -// It is recommended to use `&str` instead of `&String` here. But this is -// enough for now because we didn't handle strings yet. -fn get_char(data: &String) -> char { - data.chars().last().unwrap() -} - -// Takes ownership instead of borrowing. -fn string_uppercase(mut data: String) { - data = data.to_uppercase(); - - println!("{data}"); -} - -fn main() { - let data = "Rust is great!".to_string(); - - get_char(&data); - - string_uppercase(data); -} diff --git a/rustlings/solutions/07_structs/structs1.rs b/rustlings/solutions/07_structs/structs1.rs deleted file mode 100644 index 98fafcc..0000000 --- a/rustlings/solutions/07_structs/structs1.rs +++ /dev/null @@ -1,49 +0,0 @@ -struct ColorRegularStruct { - red: u8, - green: u8, - blue: u8, -} - -struct ColorTupleStruct(u8, u8, u8); - -#[derive(Debug)] -struct UnitStruct; - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn regular_structs() { - let green = ColorRegularStruct { - red: 0, - green: 255, - blue: 0, - }; - - assert_eq!(green.red, 0); - assert_eq!(green.green, 255); - assert_eq!(green.blue, 0); - } - - #[test] - fn tuple_structs() { - let green = ColorTupleStruct(0, 255, 0); - - assert_eq!(green.0, 0); - assert_eq!(green.1, 255); - assert_eq!(green.2, 0); - } - - #[test] - fn unit_structs() { - let unit_struct = UnitStruct; - let message = format!("{unit_struct:?}s are fun!"); - - assert_eq!(message, "UnitStructs are fun!"); - } -} diff --git a/rustlings/solutions/07_structs/structs2.rs b/rustlings/solutions/07_structs/structs2.rs deleted file mode 100644 index 589dd93..0000000 --- a/rustlings/solutions/07_structs/structs2.rs +++ /dev/null @@ -1,51 +0,0 @@ -#[derive(Debug)] -struct Order { - name: String, - year: u32, - made_by_phone: bool, - made_by_mobile: bool, - made_by_email: bool, - item_number: u32, - count: u32, -} - -fn create_order_template() -> Order { - Order { - name: String::from("Bob"), - year: 2019, - made_by_phone: false, - made_by_mobile: false, - made_by_email: true, - item_number: 123, - count: 0, - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn your_order() { - let order_template = create_order_template(); - - let your_order = Order { - name: String::from("Hacker in Rust"), - count: 1, - // Struct update syntax - ..order_template - }; - - assert_eq!(your_order.name, "Hacker in Rust"); - assert_eq!(your_order.year, order_template.year); - assert_eq!(your_order.made_by_phone, order_template.made_by_phone); - assert_eq!(your_order.made_by_mobile, order_template.made_by_mobile); - assert_eq!(your_order.made_by_email, order_template.made_by_email); - assert_eq!(your_order.item_number, order_template.item_number); - assert_eq!(your_order.count, 1); - } -} diff --git a/rustlings/solutions/07_structs/structs3.rs b/rustlings/solutions/07_structs/structs3.rs deleted file mode 100644 index 3f878cc..0000000 --- a/rustlings/solutions/07_structs/structs3.rs +++ /dev/null @@ -1,83 +0,0 @@ -#[derive(Debug)] -struct Package { - sender_country: String, - recipient_country: String, - weight_in_grams: u32, -} - -impl Package { - fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self { - if weight_in_grams < 10 { - // This isn't how you should handle errors in Rust, but we will - // learn about error handling later. - panic!("Can't ship a package with weight below 10 grams"); - } - - Self { - sender_country, - recipient_country, - weight_in_grams, - } - } - - fn is_international(&self) -> bool { - // ^^^^^^^ added - self.sender_country != self.recipient_country - } - - fn get_fees(&self, cents_per_gram: u32) -> u32 { - // ^^^^^^ added - self.weight_in_grams * cents_per_gram - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[should_panic] - fn fail_creating_weightless_package() { - let sender_country = String::from("Spain"); - let recipient_country = String::from("Austria"); - - Package::new(sender_country, recipient_country, 5); - } - - #[test] - fn create_international_package() { - let sender_country = String::from("Spain"); - let recipient_country = String::from("Russia"); - - let package = Package::new(sender_country, recipient_country, 1200); - - assert!(package.is_international()); - } - - #[test] - fn create_local_package() { - let sender_country = String::from("Canada"); - let recipient_country = sender_country.clone(); - - let package = Package::new(sender_country, recipient_country, 1200); - - assert!(!package.is_international()); - } - - #[test] - fn calculate_transport_fees() { - let sender_country = String::from("Spain"); - let recipient_country = String::from("Spain"); - - let cents_per_gram = 3; - - let package = Package::new(sender_country, recipient_country, 1500); - - assert_eq!(package.get_fees(cents_per_gram), 4500); - assert_eq!(package.get_fees(cents_per_gram * 2), 9000); - } -} diff --git a/rustlings/solutions/08_enums/enums1.rs b/rustlings/solutions/08_enums/enums1.rs deleted file mode 100644 index 97a5cc0..0000000 --- a/rustlings/solutions/08_enums/enums1.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[derive(Debug)] -enum Message { - Resize, - Move, - Echo, - ChangeColor, - Quit, -} - -fn main() { - println!("{:?}", Message::Resize); - println!("{:?}", Message::Move); - println!("{:?}", Message::Echo); - println!("{:?}", Message::ChangeColor); - println!("{:?}", Message::Quit); -} diff --git a/rustlings/solutions/08_enums/enums2.rs b/rustlings/solutions/08_enums/enums2.rs deleted file mode 100644 index 07aee26..0000000 --- a/rustlings/solutions/08_enums/enums2.rs +++ /dev/null @@ -1,37 +0,0 @@ -#[derive(Debug)] -struct Point { - x: u64, - y: u64, -} - -#[derive(Debug)] -enum Message { - Resize { width: u64, height: u64 }, - Move(Point), - Echo(String), - ChangeColor(u8, u8, u8), - Quit, -} - -impl Message { - fn call(&self) { - println!("{self:?}"); - } -} - -fn main() { - let messages = [ - Message::Resize { - width: 10, - height: 30, - }, - Message::Move(Point { x: 10, y: 15 }), - Message::Echo(String::from("hello world")), - Message::ChangeColor(200, 255, 255), - Message::Quit, - ]; - - for message in &messages { - message.call(); - } -} diff --git a/rustlings/solutions/08_enums/enums3.rs b/rustlings/solutions/08_enums/enums3.rs deleted file mode 100644 index 94cf250..0000000 --- a/rustlings/solutions/08_enums/enums3.rs +++ /dev/null @@ -1,92 +0,0 @@ -struct Point { - x: u64, - y: u64, -} - -enum Message { - Resize { width: u64, height: u64 }, - Move(Point), - Echo(String), - ChangeColor(u8, u8, u8), - Quit, -} - -struct State { - width: u64, - height: u64, - position: Point, - message: String, - color: (u8, u8, u8), - quit: bool, -} - -impl State { - fn resize(&mut self, width: u64, height: u64) { - self.width = width; - self.height = height; - } - - fn move_position(&mut self, point: Point) { - self.position = point; - } - - fn echo(&mut self, s: String) { - self.message = s; - } - - fn change_color(&mut self, red: u8, green: u8, blue: u8) { - self.color = (red, green, blue); - } - - fn quit(&mut self) { - self.quit = true; - } - - fn process(&mut self, message: Message) { - match message { - Message::Resize { width, height } => self.resize(width, height), - Message::Move(point) => self.move_position(point), - Message::Echo(string) => self.echo(string), - Message::ChangeColor(red, green, blue) => self.change_color(red, green, blue), - Message::Quit => self.quit(), - } - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_match_message_call() { - let mut state = State { - width: 0, - height: 0, - position: Point { x: 0, y: 0 }, - message: String::from("hello world"), - color: (0, 0, 0), - quit: false, - }; - - state.process(Message::Resize { - width: 10, - height: 30, - }); - state.process(Message::Move(Point { x: 10, y: 15 })); - state.process(Message::Echo(String::from("Hello world!"))); - state.process(Message::ChangeColor(255, 0, 255)); - state.process(Message::Quit); - - assert_eq!(state.width, 10); - assert_eq!(state.height, 30); - assert_eq!(state.position.x, 10); - assert_eq!(state.position.y, 15); - assert_eq!(state.message, "Hello world!"); - assert_eq!(state.color, (255, 0, 255)); - assert!(state.quit); - } -} diff --git a/rustlings/solutions/09_strings/strings1.rs b/rustlings/solutions/09_strings/strings1.rs deleted file mode 100644 index f7ba811..0000000 --- a/rustlings/solutions/09_strings/strings1.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn current_favorite_color() -> String { - // Equivalent to `String::from("blue")` - "blue".to_string() -} - -fn main() { - let answer = current_favorite_color(); - println!("My current favorite color is {answer}"); -} diff --git a/rustlings/solutions/09_strings/strings2.rs b/rustlings/solutions/09_strings/strings2.rs deleted file mode 100644 index 7de311f..0000000 --- a/rustlings/solutions/09_strings/strings2.rs +++ /dev/null @@ -1,15 +0,0 @@ -fn is_a_color_word(attempt: &str) -> bool { - attempt == "green" || attempt == "blue" || attempt == "red" -} - -fn main() { - let word = String::from("green"); - - if is_a_color_word(&word) { - // ^ added to have `&String` which is automatically - // coerced to `&str` by the compiler. - println!("That is a color word I know!"); - } else { - println!("That is not a color word I know."); - } -} diff --git a/rustlings/solutions/09_strings/strings3.rs b/rustlings/solutions/09_strings/strings3.rs deleted file mode 100644 index ee6b56a..0000000 --- a/rustlings/solutions/09_strings/strings3.rs +++ /dev/null @@ -1,49 +0,0 @@ -fn trim_me(input: &str) -> &str { - input.trim() -} - -fn compose_me(input: &str) -> String { - // The macro `format!` has the same syntax as `println!`, but it returns a - // string instead of printing it to the terminal. - // Equivalent to `input.to_string() + " world!"` - format!("{input} world!") -} - -fn replace_me(input: &str) -> String { - input.replace("cars", "balloons") -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn trim_a_string() { - assert_eq!(trim_me("Hello! "), "Hello!"); - assert_eq!(trim_me(" What's up!"), "What's up!"); - assert_eq!(trim_me(" Hola! "), "Hola!"); - assert_eq!(trim_me("Hi!"), "Hi!"); - } - - #[test] - fn compose_a_string() { - assert_eq!(compose_me("Hello"), "Hello world!"); - assert_eq!(compose_me("Goodbye"), "Goodbye world!"); - } - - #[test] - fn replace_a_string() { - assert_eq!( - replace_me("I think cars are cool"), - "I think balloons are cool", - ); - assert_eq!( - replace_me("I love to look at cars"), - "I love to look at balloons", - ); - } -} diff --git a/rustlings/solutions/09_strings/strings4.rs b/rustlings/solutions/09_strings/strings4.rs deleted file mode 100644 index 3c69b97..0000000 --- a/rustlings/solutions/09_strings/strings4.rs +++ /dev/null @@ -1,38 +0,0 @@ -fn string_slice(arg: &str) { - println!("{arg}"); -} - -fn string(arg: String) { - println!("{arg}"); -} - -fn main() { - string_slice("blue"); - - string("red".to_string()); - - string(String::from("hi")); - - string("rust is fun!".to_owned()); - - // Here, both answers work. - // `.into()` converts a type into an expected type. - // If it is called where `String` is expected, it will convert `&str` to `String`. - string("nice weather".into()); - // But if it is called where `&str` is expected, then `&str` is kept `&str` since no conversion is needed. - // If you remove the `#[allow(…)]` line, then Clippy will tell you to remove `.into()` below since it is a useless conversion. - #[allow(clippy::useless_conversion)] - string_slice("nice weather".into()); - - string(format!("Interpolation {}", "Station")); - - // WARNING: This is byte indexing, not character indexing. - // Character indexing can be done using `s.chars().nth(INDEX)`. - string_slice(&String::from("abc")[0..1]); - - string_slice(" hello there ".trim()); - - string("Happy Monday!".replace("Mon", "Tues")); - - string("mY sHiFt KeY iS sTiCkY".to_lowercase()); -} diff --git a/rustlings/solutions/10_modules/modules1.rs b/rustlings/solutions/10_modules/modules1.rs deleted file mode 100644 index 873b412..0000000 --- a/rustlings/solutions/10_modules/modules1.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod sausage_factory { - fn get_secret_recipe() -> String { - String::from("Ginger") - } - - // Added `pub` before `fn` to make the function accessible outside the module. - pub fn make_sausage() { - get_secret_recipe(); - println!("sausage!"); - } -} - -fn main() { - sausage_factory::make_sausage(); -} diff --git a/rustlings/solutions/10_modules/modules2.rs b/rustlings/solutions/10_modules/modules2.rs deleted file mode 100644 index 55c316d..0000000 --- a/rustlings/solutions/10_modules/modules2.rs +++ /dev/null @@ -1,23 +0,0 @@ -mod delicious_snacks { - // Added `pub` and used the expected alias after `as`. - pub use self::fruits::PEAR as fruit; - pub use self::veggies::CUCUMBER as veggie; - - mod fruits { - pub const PEAR: &str = "Pear"; - pub const APPLE: &str = "Apple"; - } - - mod veggies { - pub const CUCUMBER: &str = "Cucumber"; - pub const CARROT: &str = "Carrot"; - } -} - -fn main() { - println!( - "favorite snacks: {} and {}", - delicious_snacks::fruit, - delicious_snacks::veggie, - ); -} diff --git a/rustlings/solutions/10_modules/modules3.rs b/rustlings/solutions/10_modules/modules3.rs deleted file mode 100644 index 99ff5a7..0000000 --- a/rustlings/solutions/10_modules/modules3.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::time::{SystemTime, UNIX_EPOCH}; - -fn main() { - match SystemTime::now().duration_since(UNIX_EPOCH) { - Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), - Err(_) => panic!("SystemTime before UNIX EPOCH!"), - } -} diff --git a/rustlings/solutions/11_hashmaps/hashmaps1.rs b/rustlings/solutions/11_hashmaps/hashmaps1.rs deleted file mode 100644 index 3a787c4..0000000 --- a/rustlings/solutions/11_hashmaps/hashmaps1.rs +++ /dev/null @@ -1,42 +0,0 @@ -// A basket of fruits in the form of a hash map needs to be defined. The key -// represents the name of the fruit and the value represents how many of that -// particular fruit is in the basket. You have to put at least 3 different -// types of fruits (e.g apple, banana, mango) in the basket and the total count -// of all the fruits should be at least 5. - -use std::collections::HashMap; - -fn fruit_basket() -> HashMap<String, u32> { - // Declare the hash map. - let mut basket = HashMap::new(); - - // Two bananas are already given for you :) - basket.insert(String::from("banana"), 2); - - // Put more fruits in your basket. - basket.insert(String::from("apple"), 3); - basket.insert(String::from("mango"), 1); - - basket -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn at_least_three_types_of_fruits() { - let basket = fruit_basket(); - assert!(basket.len() >= 3); - } - - #[test] - fn at_least_five_fruits() { - let basket = fruit_basket(); - assert!(basket.values().sum::<u32>() >= 5); - } -} diff --git a/rustlings/solutions/11_hashmaps/hashmaps2.rs b/rustlings/solutions/11_hashmaps/hashmaps2.rs deleted file mode 100644 index 75e6ec2..0000000 --- a/rustlings/solutions/11_hashmaps/hashmaps2.rs +++ /dev/null @@ -1,96 +0,0 @@ -// We're collecting different fruits to bake a delicious fruit cake. For this, -// we have a basket, which we'll represent in the form of a hash map. The key -// represents the name of each fruit we collect and the value represents how -// many of that particular fruit we have collected. Three types of fruits - -// Apple (4), Mango (2) and Lychee (5) are already in the basket hash map. You -// must add fruit to the basket so that there is at least one of each kind and -// more than 11 in total - we have a lot of mouths to feed. You are not allowed -// to insert any more of the fruits that are already in the basket (Apple, -// Mango, and Lychee). - -use std::collections::HashMap; - -#[derive(Hash, PartialEq, Eq, Debug)] -enum Fruit { - Apple, - Banana, - Mango, - Lychee, - Pineapple, -} - -fn fruit_basket(basket: &mut HashMap<Fruit, u32>) { - let fruit_kinds = [ - Fruit::Apple, - Fruit::Banana, - Fruit::Mango, - Fruit::Lychee, - Fruit::Pineapple, - ]; - - for fruit in fruit_kinds { - // If fruit doesn't exist, insert it with some value. - basket.entry(fruit).or_insert(5); - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - // Don't modify this function! - fn get_fruit_basket() -> HashMap<Fruit, u32> { - let content = [(Fruit::Apple, 4), (Fruit::Mango, 2), (Fruit::Lychee, 5)]; - HashMap::from_iter(content) - } - - #[test] - fn test_given_fruits_are_not_modified() { - let mut basket = get_fruit_basket(); - fruit_basket(&mut basket); - assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4); - assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2); - assert_eq!(*basket.get(&Fruit::Lychee).unwrap(), 5); - } - - #[test] - fn at_least_five_types_of_fruits() { - let mut basket = get_fruit_basket(); - fruit_basket(&mut basket); - let count_fruit_kinds = basket.len(); - assert!(count_fruit_kinds >= 5); - } - - #[test] - fn greater_than_eleven_fruits() { - let mut basket = get_fruit_basket(); - fruit_basket(&mut basket); - let count = basket.values().sum::<u32>(); - assert!(count > 11); - } - - #[test] - fn all_fruit_types_in_basket() { - let fruit_kinds = [ - Fruit::Apple, - Fruit::Banana, - Fruit::Mango, - Fruit::Lychee, - Fruit::Pineapple, - ]; - - let mut basket = get_fruit_basket(); - fruit_basket(&mut basket); - - for fruit_kind in fruit_kinds { - let Some(amount) = basket.get(&fruit_kind) else { - panic!("Fruit kind {fruit_kind:?} was not found in basket"); - }; - assert!(*amount > 0); - } - } -} diff --git a/rustlings/solutions/11_hashmaps/hashmaps3.rs b/rustlings/solutions/11_hashmaps/hashmaps3.rs deleted file mode 100644 index 485bf83..0000000 --- a/rustlings/solutions/11_hashmaps/hashmaps3.rs +++ /dev/null @@ -1,85 +0,0 @@ -// A list of scores (one per line) of a soccer match is given. Each line is of -// the form "<team_1_name>,<team_2_name>,<team_1_goals>,<team_2_goals>" -// Example: "England,France,4,2" (England scored 4 goals, France 2). -// -// You have to build a scores table containing the name of the team, the total -// number of goals the team scored, and the total number of goals the team -// conceded. - -use std::collections::HashMap; - -// A structure to store the goal details of a team. -#[derive(Default)] -struct TeamScores { - goals_scored: u8, - goals_conceded: u8, -} - -fn build_scores_table(results: &str) -> HashMap<&str, TeamScores> { - // The name of the team is the key and its associated struct is the value. - let mut scores = HashMap::<&str, TeamScores>::new(); - - for line in results.lines() { - let mut split_iterator = line.split(','); - // NOTE: We use `unwrap` because we didn't deal with error handling yet. - let team_1_name = split_iterator.next().unwrap(); - let team_2_name = split_iterator.next().unwrap(); - let team_1_score: u8 = split_iterator.next().unwrap().parse().unwrap(); - let team_2_score: u8 = split_iterator.next().unwrap().parse().unwrap(); - - // Insert the default with zeros if a team doesn't exist yet. - let team_1 = scores.entry(team_1_name).or_default(); - // Update the values. - team_1.goals_scored += team_1_score; - team_1.goals_conceded += team_2_score; - - // Similarly for the second team. - let team_2 = scores.entry(team_2_name).or_default(); - team_2.goals_scored += team_2_score; - team_2.goals_conceded += team_1_score; - } - - scores -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - const RESULTS: &str = "England,France,4,2 -France,Italy,3,1 -Poland,Spain,2,0 -Germany,England,2,1 -England,Spain,1,0"; - - #[test] - fn build_scores() { - let scores = build_scores_table(RESULTS); - - assert!( - ["England", "France", "Germany", "Italy", "Poland", "Spain"] - .into_iter() - .all(|team_name| scores.contains_key(team_name)) - ); - } - - #[test] - fn validate_team_score_1() { - let scores = build_scores_table(RESULTS); - let team = scores.get("England").unwrap(); - assert_eq!(team.goals_scored, 6); - assert_eq!(team.goals_conceded, 4); - } - - #[test] - fn validate_team_score_2() { - let scores = build_scores_table(RESULTS); - let team = scores.get("Spain").unwrap(); - assert_eq!(team.goals_scored, 0); - assert_eq!(team.goals_conceded, 3); - } -} diff --git a/rustlings/solutions/12_options/options1.rs b/rustlings/solutions/12_options/options1.rs deleted file mode 100644 index 4d615dd..0000000 --- a/rustlings/solutions/12_options/options1.rs +++ /dev/null @@ -1,39 +0,0 @@ -// This function returns how much icecream there is left in the fridge. -// If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00, -// someone eats it all, so no icecream is left (value 0). Return `None` if -// `hour_of_day` is higher than 23. -fn maybe_icecream(hour_of_day: u16) -> Option<u16> { - match hour_of_day { - 0..=21 => Some(5), - 22..=23 => Some(0), - _ => None, - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn raw_value() { - // Using `unwrap` is fine in a test. - let icecreams = maybe_icecream(12).unwrap(); - - assert_eq!(icecreams, 5); - } - - #[test] - fn check_icecream() { - assert_eq!(maybe_icecream(0), Some(5)); - assert_eq!(maybe_icecream(9), Some(5)); - assert_eq!(maybe_icecream(18), Some(5)); - assert_eq!(maybe_icecream(22), Some(0)); - assert_eq!(maybe_icecream(23), Some(0)); - assert_eq!(maybe_icecream(24), None); - assert_eq!(maybe_icecream(25), None); - } -} diff --git a/rustlings/solutions/12_options/options2.rs b/rustlings/solutions/12_options/options2.rs deleted file mode 100644 index 0f24665..0000000 --- a/rustlings/solutions/12_options/options2.rs +++ /dev/null @@ -1,37 +0,0 @@ -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - #[test] - fn simple_option() { - let target = "rustlings"; - let optional_target = Some(target); - - // if-let - if let Some(word) = optional_target { - assert_eq!(word, target); - } - } - - #[test] - fn layered_option() { - let range = 10; - let mut optional_integers: Vec<Option<i8>> = vec![None]; - - for i in 1..=range { - optional_integers.push(Some(i)); - } - - let mut cursor = range; - - // while-let with nested pattern matching - while let Some(Some(integer)) = optional_integers.pop() { - assert_eq!(integer, cursor); - cursor -= 1; - } - - assert_eq!(cursor, 0); - } -} diff --git a/rustlings/solutions/12_options/options3.rs b/rustlings/solutions/12_options/options3.rs deleted file mode 100644 index c918f71..0000000 --- a/rustlings/solutions/12_options/options3.rs +++ /dev/null @@ -1,27 +0,0 @@ -#[derive(Debug)] -struct Point { - x: i32, - y: i32, -} - -fn main() { - let optional_point = Some(Point { x: 100, y: 200 }); - - // Solution 1: Matching over the `Option` (not `&Option`) but without moving - // out of the `Some` variant. - match optional_point { - Some(ref p) => println!("Coordinates are {},{}", p.x, p.y), - // ^^^ added - _ => panic!("No match!"), - } - - // Solution 2: Matching over a reference (`&Option`) by added `&` before - // `optional_point`. - match &optional_point { - //^ added - Some(p) => println!("Coordinates are {},{}", p.x, p.y), - _ => panic!("No match!"), - } - - println!("{optional_point:?}"); -} diff --git a/rustlings/solutions/13_error_handling/errors1.rs b/rustlings/solutions/13_error_handling/errors1.rs deleted file mode 100644 index f552ca7..0000000 --- a/rustlings/solutions/13_error_handling/errors1.rs +++ /dev/null @@ -1,37 +0,0 @@ -fn generate_nametag_text(name: String) -> Result<String, String> { - // ^^^^^^ ^^^^^^ - if name.is_empty() { - // `Err(String)` instead of `None`. - Err("Empty names aren't allowed".to_string()) - } else { - // `Ok` instead of `Some`. - Ok(format!("Hi! My name is {name}")) - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn generates_nametag_text_for_a_nonempty_name() { - assert_eq!( - generate_nametag_text("Beyoncé".to_string()).as_deref(), - Ok("Hi! My name is Beyoncé"), - ); - } - - #[test] - fn explains_why_generating_nametag_text_fails() { - assert_eq!( - generate_nametag_text(String::new()) - .as_ref() - .map_err(|e| e.as_str()), - Err("Empty names aren't allowed"), - ); - } -} diff --git a/rustlings/solutions/13_error_handling/errors2.rs b/rustlings/solutions/13_error_handling/errors2.rs deleted file mode 100644 index f0e144e..0000000 --- a/rustlings/solutions/13_error_handling/errors2.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Say we're writing a game where you can buy items with tokens. All items cost -// 5 tokens, and whenever you purchase items there is a processing fee of 1 -// token. A player of the game will type in how many items they want to buy, and -// the `total_cost` function will calculate the total cost of the items. Since -// the player typed in the quantity, we get it as a string. They might have -// typed anything, not just numbers! -// -// Right now, this function isn't handling the error case at all. What we want -// to do is: If we call the `total_cost` function on a string that is not a -// number, that function will return a `ParseIntError`. In that case, we want to -// immediately return that error from our function and not try to multiply and -// add. -// -// There are at least two ways to implement this that are both correct. But one -// is a lot shorter! - -use std::num::ParseIntError; - -#[allow(unused_variables, clippy::question_mark)] -fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> { - let processing_fee = 1; - let cost_per_item = 5; - - // Added `?` to propagate the error. - let qty = item_quantity.parse::<i32>()?; - // ^ added - - // Equivalent to this verbose version: - let qty = match item_quantity.parse::<i32>() { - Ok(v) => v, - Err(e) => return Err(e), - }; - - Ok(qty * cost_per_item + processing_fee) -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - use std::num::IntErrorKind; - - #[test] - fn item_quantity_is_a_valid_number() { - assert_eq!(total_cost("34"), Ok(171)); - } - - #[test] - fn item_quantity_is_an_invalid_number() { - assert_eq!( - total_cost("beep boop").unwrap_err().kind(), - &IntErrorKind::InvalidDigit, - ); - } -} diff --git a/rustlings/solutions/13_error_handling/errors3.rs b/rustlings/solutions/13_error_handling/errors3.rs deleted file mode 100644 index 63f4aba..0000000 --- a/rustlings/solutions/13_error_handling/errors3.rs +++ /dev/null @@ -1,32 +0,0 @@ -// This is a program that is trying to use a completed version of the -// `total_cost` function from the previous exercise. It's not working though! -// Why not? What should we do to fix it? - -use std::num::ParseIntError; - -// Don't change this function. -fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> { - let processing_fee = 1; - let cost_per_item = 5; - let qty = item_quantity.parse::<i32>()?; - - Ok(qty * cost_per_item + processing_fee) -} - -fn main() -> Result<(), ParseIntError> { - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ added - let mut tokens = 100; - let pretend_user_input = "8"; - - let cost = total_cost(pretend_user_input)?; - - if cost > tokens { - println!("You can't afford that many!"); - } else { - tokens -= cost; - println!("You now have {tokens} tokens."); - } - - // Added this line to return the `Ok` variant of the expected `Result`. - Ok(()) -} diff --git a/rustlings/solutions/13_error_handling/errors4.rs b/rustlings/solutions/13_error_handling/errors4.rs deleted file mode 100644 index 70c5f1c..0000000 --- a/rustlings/solutions/13_error_handling/errors4.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::cmp::Ordering; - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result<Self, CreationError> { - match value.cmp(&0) { - Ordering::Less => Err(CreationError::Negative), - Ordering::Equal => Err(CreationError::Zero), - Ordering::Greater => Ok(Self(value as u64)), - } - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_creation() { - assert_eq!( - PositiveNonzeroInteger::new(10), - Ok(PositiveNonzeroInteger(10)), - ); - assert_eq!( - PositiveNonzeroInteger::new(-10), - Err(CreationError::Negative), - ); - assert_eq!(PositiveNonzeroInteger::new(0), Err(CreationError::Zero)); - } -} diff --git a/rustlings/solutions/13_error_handling/errors5.rs b/rustlings/solutions/13_error_handling/errors5.rs deleted file mode 100644 index c1424ee..0000000 --- a/rustlings/solutions/13_error_handling/errors5.rs +++ /dev/null @@ -1,54 +0,0 @@ -// This exercise is an altered version of the `errors4` exercise. It uses some -// concepts that we won't get to until later in the course, like `Box` and the -// `From` trait. It's not important to understand them in detail right now, but -// you can read ahead if you like. For now, think of the `Box<dyn ???>` type as -// an "I want anything that does ???" type. -// -// In short, this particular use case for boxes is for when you want to own a -// value and you care only that it is a type which implements a particular -// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where -// `Trait` is the trait the compiler looks for on any value used in that -// context. For this exercise, that context is the potential errors which -// can be returned in a `Result`. - -use std::error::Error; -use std::fmt; - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -// This is required so that `CreationError` can implement `Error`. -impl fmt::Display for CreationError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let description = match *self { - CreationError::Negative => "number is negative", - CreationError::Zero => "number is zero", - }; - f.write_str(description) - } -} - -impl Error for CreationError {} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { - match value { - x if x < 0 => Err(CreationError::Negative), - 0 => Err(CreationError::Zero), - x => Ok(PositiveNonzeroInteger(x as u64)), - } - } -} - -fn main() -> Result<(), Box<dyn Error>> { - let pretend_user_input = "42"; - let x: i64 = pretend_user_input.parse()?; - println!("output={:?}", PositiveNonzeroInteger::new(x)?); - Ok(()) -} diff --git a/rustlings/solutions/13_error_handling/errors6.rs b/rustlings/solutions/13_error_handling/errors6.rs deleted file mode 100644 index ce18073..0000000 --- a/rustlings/solutions/13_error_handling/errors6.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Using catch-all error types like `Box<dyn Error>` isn't recommended for -// library code where callers might want to make decisions based on the error -// content instead of printing it out or propagating it further. Here, we define -// a custom error type to make it possible for callers to decide what to do next -// when our function returns an error. - -use std::num::ParseIntError; - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -// A custom error type that we will be using in `PositiveNonzeroInteger::parse`. -#[derive(PartialEq, Debug)] -enum ParsePosNonzeroError { - Creation(CreationError), - ParseInt(ParseIntError), -} - -impl ParsePosNonzeroError { - fn from_creation(err: CreationError) -> Self { - Self::Creation(err) - } - - fn from_parse_int(err: ParseIntError) -> Self { - Self::ParseInt(err) - } -} - -// As an alternative solution, implementing the `From` trait allows for the -// automatic conversion from a `ParseIntError` into a `ParsePosNonzeroError` -// using the `?` operator, without the need to call `map_err`. -// -// ``` -// let x: i64 = s.parse()?; -// ``` -// -// Traits like `From` will be dealt with in later exercises. -impl From<ParseIntError> for ParsePosNonzeroError { - fn from(err: ParseIntError) -> Self { - ParsePosNonzeroError::ParseInt(err) - } -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result<Self, CreationError> { - match value { - x if x < 0 => Err(CreationError::Negative), - 0 => Err(CreationError::Zero), - x => Ok(Self(x as u64)), - } - } - - fn parse(s: &str) -> Result<Self, ParsePosNonzeroError> { - // Return an appropriate error instead of panicking when `parse()` - // returns an error. - let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?; - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Self::new(x).map_err(ParsePosNonzeroError::from_creation) - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_error() { - assert!(matches!( - PositiveNonzeroInteger::parse("not a number"), - Err(ParsePosNonzeroError::ParseInt(_)), - )); - } - - #[test] - fn test_negative() { - assert_eq!( - PositiveNonzeroInteger::parse("-555"), - Err(ParsePosNonzeroError::Creation(CreationError::Negative)), - ); - } - - #[test] - fn test_zero() { - assert_eq!( - PositiveNonzeroInteger::parse("0"), - Err(ParsePosNonzeroError::Creation(CreationError::Zero)), - ); - } - - #[test] - fn test_positive() { - let x = PositiveNonzeroInteger::new(42).unwrap(); - assert_eq!(x.0, 42); - assert_eq!(PositiveNonzeroInteger::parse("42"), Ok(x)); - } -} diff --git a/rustlings/solutions/14_generics/generics1.rs b/rustlings/solutions/14_generics/generics1.rs deleted file mode 100644 index e2195fd..0000000 --- a/rustlings/solutions/14_generics/generics1.rs +++ /dev/null @@ -1,17 +0,0 @@ -// `Vec<T>` is generic over the type `T`. In most cases, the compiler is able to -// infer `T`, for example after pushing a value with a concrete type to the vector. -// But in this exercise, the compiler needs some help through a type annotation. - -fn main() { - // `u8` and `i8` can both be converted to `i16`. - let mut numbers: Vec<i16> = Vec::new(); - // ^^^^^^^^^^ added - - // Don't change the lines below. - let n1: u8 = 42; - numbers.push(n1.into()); - let n2: i8 = -1; - numbers.push(n2.into()); - - println!("{numbers:?}"); -} diff --git a/rustlings/solutions/14_generics/generics2.rs b/rustlings/solutions/14_generics/generics2.rs deleted file mode 100644 index 14f3f7a..0000000 --- a/rustlings/solutions/14_generics/generics2.rs +++ /dev/null @@ -1,28 +0,0 @@ -struct Wrapper<T> { - value: T, -} - -impl<T> Wrapper<T> { - fn new(value: T) -> Self { - Wrapper { value } - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn store_u32_in_wrapper() { - assert_eq!(Wrapper::new(42).value, 42); - } - - #[test] - fn store_str_in_wrapper() { - assert_eq!(Wrapper::new("Foo").value, "Foo"); - } -} diff --git a/rustlings/solutions/15_traits/traits1.rs b/rustlings/solutions/15_traits/traits1.rs deleted file mode 100644 index 790873f..0000000 --- a/rustlings/solutions/15_traits/traits1.rs +++ /dev/null @@ -1,32 +0,0 @@ -// The trait `AppendBar` has only one function which appends "Bar" to any object -// implementing this trait. -trait AppendBar { - fn append_bar(self) -> Self; -} - -impl AppendBar for String { - fn append_bar(self) -> Self { - self + "Bar" - } -} - -fn main() { - let s = String::from("Foo"); - let s = s.append_bar(); - println!("s: {s}"); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn is_foo_bar() { - assert_eq!(String::from("Foo").append_bar(), "FooBar"); - } - - #[test] - fn is_bar_bar() { - assert_eq!(String::from("").append_bar().append_bar(), "BarBar"); - } -} diff --git a/rustlings/solutions/15_traits/traits2.rs b/rustlings/solutions/15_traits/traits2.rs deleted file mode 100644 index 0db93e0..0000000 --- a/rustlings/solutions/15_traits/traits2.rs +++ /dev/null @@ -1,27 +0,0 @@ -trait AppendBar { - fn append_bar(self) -> Self; -} - -impl AppendBar for Vec<String> { - fn append_bar(mut self) -> Self { - // ^^^ this is important - self.push(String::from("Bar")); - self - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn is_vec_pop_eq_bar() { - let mut foo = vec![String::from("Foo")].append_bar(); - assert_eq!(foo.pop().unwrap(), "Bar"); - assert_eq!(foo.pop().unwrap(), "Foo"); - } -} diff --git a/rustlings/solutions/15_traits/traits3.rs b/rustlings/solutions/15_traits/traits3.rs deleted file mode 100644 index 3d8ec85..0000000 --- a/rustlings/solutions/15_traits/traits3.rs +++ /dev/null @@ -1,36 +0,0 @@ -trait Licensed { - fn licensing_info(&self) -> String { - "Default license".to_string() - } -} - -struct SomeSoftware { - version_number: i32, -} - -struct OtherSoftware { - version_number: String, -} - -impl Licensed for SomeSoftware {} -impl Licensed for OtherSoftware {} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn is_licensing_info_the_same() { - let licensing_info = "Default license"; - let some_software = SomeSoftware { version_number: 1 }; - let other_software = OtherSoftware { - version_number: "v2.0.0".to_string(), - }; - assert_eq!(some_software.licensing_info(), licensing_info); - assert_eq!(other_software.licensing_info(), licensing_info); - } -} diff --git a/rustlings/solutions/15_traits/traits4.rs b/rustlings/solutions/15_traits/traits4.rs deleted file mode 100644 index 3675b8d..0000000 --- a/rustlings/solutions/15_traits/traits4.rs +++ /dev/null @@ -1,35 +0,0 @@ -trait Licensed { - fn licensing_info(&self) -> String { - "Default license".to_string() - } -} - -struct SomeSoftware; -struct OtherSoftware; - -impl Licensed for SomeSoftware {} -impl Licensed for OtherSoftware {} - -fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool { - // ^^^^^^^^^^^^^ ^^^^^^^^^^^^^ - software1.licensing_info() == software2.licensing_info() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn compare_license_information() { - assert!(compare_license_types(SomeSoftware, OtherSoftware)); - } - - #[test] - fn compare_license_information_backwards() { - assert!(compare_license_types(OtherSoftware, SomeSoftware)); - } -} diff --git a/rustlings/solutions/15_traits/traits5.rs b/rustlings/solutions/15_traits/traits5.rs deleted file mode 100644 index 1fb426a..0000000 --- a/rustlings/solutions/15_traits/traits5.rs +++ /dev/null @@ -1,39 +0,0 @@ -trait SomeTrait { - fn some_function(&self) -> bool { - true - } -} - -trait OtherTrait { - fn other_function(&self) -> bool { - true - } -} - -struct SomeStruct; -impl SomeTrait for SomeStruct {} -impl OtherTrait for SomeStruct {} - -struct OtherStruct; -impl SomeTrait for OtherStruct {} -impl OtherTrait for OtherStruct {} - -fn some_func(item: impl SomeTrait + OtherTrait) -> bool { - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - item.some_function() && item.other_function() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_some_func() { - assert!(some_func(SomeStruct)); - assert!(some_func(OtherStruct)); - } -} diff --git a/rustlings/solutions/16_lifetimes/lifetimes1.rs b/rustlings/solutions/16_lifetimes/lifetimes1.rs deleted file mode 100644 index 4f56834..0000000 --- a/rustlings/solutions/16_lifetimes/lifetimes1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// The Rust compiler needs to know how to check whether supplied references are -// valid, so that it can let the programmer know if a reference is at risk of -// going out of scope before it is used. Remember, references are borrows and do -// not own their own data. What if their owner goes out of scope? - -fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { - // ^^^^ ^^ ^^ ^^ - if x.len() > y.len() { x } else { y } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_longest() { - assert_eq!(longest("abcd", "123"), "abcd"); - assert_eq!(longest("abc", "1234"), "1234"); - } -} diff --git a/rustlings/solutions/16_lifetimes/lifetimes2.rs b/rustlings/solutions/16_lifetimes/lifetimes2.rs deleted file mode 100644 index 3ca4909..0000000 --- a/rustlings/solutions/16_lifetimes/lifetimes2.rs +++ /dev/null @@ -1,29 +0,0 @@ -fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { - if x.len() > y.len() { x } else { y } -} - -fn main() { - let string1 = String::from("long string is long"); - // Solution1: You can move `strings2` out of the inner block so that it is - // not dropped before the print statement. - let string2 = String::from("xyz"); - let result; - { - result = longest(&string1, &string2); - } - println!("The longest string is '{result}'"); - // `string2` dropped at the end of the function. - - // ========================================================================= - - let string1 = String::from("long string is long"); - let result; - { - let string2 = String::from("xyz"); - result = longest(&string1, &string2); - // Solution2: You can move the print statement into the inner block so - // that it is executed before `string2` is dropped. - println!("The longest string is '{result}'"); - // `string2` dropped here (end of the inner scope). - } -} diff --git a/rustlings/solutions/16_lifetimes/lifetimes3.rs b/rustlings/solutions/16_lifetimes/lifetimes3.rs deleted file mode 100644 index 16a5a68..0000000 --- a/rustlings/solutions/16_lifetimes/lifetimes3.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Lifetimes are also needed when structs hold references. - -struct Book<'a> { - // ^^^^ added a lifetime annotation - author: &'a str, - // ^^ - title: &'a str, - // ^^ -} - -fn main() { - let book = Book { - author: "George Orwell", - title: "1984", - }; - - println!("{} by {}", book.title, book.author); -} diff --git a/rustlings/solutions/17_tests/tests1.rs b/rustlings/solutions/17_tests/tests1.rs deleted file mode 100644 index c52b8b1..0000000 --- a/rustlings/solutions/17_tests/tests1.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Tests are important to ensure that your code does what you think it should -// do. - -fn is_even(n: i64) -> bool { - n % 2 == 0 -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - // When writing unit tests, it is common to import everything from the outer - // module (`super`) using a wildcard. - use super::*; - - #[test] - fn you_can_assert() { - assert!(is_even(0)); - assert!(!is_even(-1)); - // ^ You can assert `false` using the negation operator `!`. - } -} diff --git a/rustlings/solutions/17_tests/tests2.rs b/rustlings/solutions/17_tests/tests2.rs deleted file mode 100644 index 39a0005..0000000 --- a/rustlings/solutions/17_tests/tests2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Calculates the power of 2 using a bit shift. -// `1 << n` is equivalent to "2 to the power of n". -fn power_of_2(n: u8) -> u64 { - 1 << n -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn you_can_assert_eq() { - assert_eq!(power_of_2(0), 1); - assert_eq!(power_of_2(1), 2); - assert_eq!(power_of_2(2), 4); - assert_eq!(power_of_2(3), 8); - } -} diff --git a/rustlings/solutions/17_tests/tests3.rs b/rustlings/solutions/17_tests/tests3.rs deleted file mode 100644 index 487fdc6..0000000 --- a/rustlings/solutions/17_tests/tests3.rs +++ /dev/null @@ -1,45 +0,0 @@ -struct Rectangle { - width: i32, - height: i32, -} - -impl Rectangle { - // Don't change this function. - fn new(width: i32, height: i32) -> Self { - if width <= 0 || height <= 0 { - // Returning a `Result` would be better here. But we want to learn - // how to test functions that can panic. - panic!("Rectangle width and height must be positive"); - } - - Rectangle { width, height } - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn correct_width_and_height() { - let rect = Rectangle::new(10, 20); - assert_eq!(rect.width, 10); // Check width - assert_eq!(rect.height, 20); // Check height - } - - #[test] - #[should_panic] // Added this attribute to check that the test panics. - fn negative_width() { - let _rect = Rectangle::new(-10, 10); - } - - #[test] - #[should_panic] // Added this attribute to check that the test panics. - fn negative_height() { - let _rect = Rectangle::new(10, -10); - } -} diff --git a/rustlings/solutions/18_iterators/iterators1.rs b/rustlings/solutions/18_iterators/iterators1.rs deleted file mode 100644 index 93a6008..0000000 --- a/rustlings/solutions/18_iterators/iterators1.rs +++ /dev/null @@ -1,26 +0,0 @@ -// When performing operations on elements within a collection, iterators are -// essential. This module helps you get familiar with the structure of using an -// iterator and how to go through elements within an iterable collection. - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - #[test] - fn iterators() { - let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"]; - - // Create an iterator over the array. - let mut fav_fruits_iterator = my_fav_fruits.iter(); - - assert_eq!(fav_fruits_iterator.next(), Some(&"banana")); - assert_eq!(fav_fruits_iterator.next(), Some(&"custard apple")); - assert_eq!(fav_fruits_iterator.next(), Some(&"avocado")); - assert_eq!(fav_fruits_iterator.next(), Some(&"peach")); - assert_eq!(fav_fruits_iterator.next(), Some(&"raspberry")); - assert_eq!(fav_fruits_iterator.next(), None); - // ^^^^ reached the end - } -} diff --git a/rustlings/solutions/18_iterators/iterators2.rs b/rustlings/solutions/18_iterators/iterators2.rs deleted file mode 100644 index db05f29..0000000 --- a/rustlings/solutions/18_iterators/iterators2.rs +++ /dev/null @@ -1,56 +0,0 @@ -// In this exercise, you'll learn some of the unique advantages that iterators -// can offer. - -// "hello" -> "Hello" -fn capitalize_first(input: &str) -> String { - let mut chars = input.chars(); - match chars.next() { - None => String::new(), - Some(first) => first.to_uppercase().to_string() + chars.as_str(), - } -} - -// Apply the `capitalize_first` function to a slice of string slices. -// Return a vector of strings. -// ["hello", "world"] -> ["Hello", "World"] -fn capitalize_words_vector(words: &[&str]) -> Vec<String> { - words.iter().map(|word| capitalize_first(word)).collect() -} - -// Apply the `capitalize_first` function again to a slice of string -// slices. Return a single string. -// ["hello", " ", "world"] -> "Hello World" -fn capitalize_words_string(words: &[&str]) -> String { - words.iter().map(|word| capitalize_first(word)).collect() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_success() { - assert_eq!(capitalize_first("hello"), "Hello"); - } - - #[test] - fn test_empty() { - assert_eq!(capitalize_first(""), ""); - } - - #[test] - fn test_iterate_string_vec() { - let words = vec!["hello", "world"]; - assert_eq!(capitalize_words_vector(&words), ["Hello", "World"]); - } - - #[test] - fn test_iterate_into_string() { - let words = vec!["hello", " ", "world"]; - assert_eq!(capitalize_words_string(&words), "Hello World"); - } -} diff --git a/rustlings/solutions/18_iterators/iterators3.rs b/rustlings/solutions/18_iterators/iterators3.rs deleted file mode 100644 index 1d5d67f..0000000 --- a/rustlings/solutions/18_iterators/iterators3.rs +++ /dev/null @@ -1,88 +0,0 @@ -#[derive(Debug, PartialEq, Eq)] -enum DivisionError { - // Example: 42 / 0 - DivideByZero, - // Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1` - IntegerOverflow, - // Example: 5 / 2 = 2.5 - NotDivisible, -} - -fn divide(a: i64, b: i64) -> Result<i64, DivisionError> { - if b == 0 { - return Err(DivisionError::DivideByZero); - } - - if a == i64::MIN && b == -1 { - return Err(DivisionError::IntegerOverflow); - } - - if a % b != 0 { - return Err(DivisionError::NotDivisible); - } - - Ok(a / b) -} - -fn result_with_list() -> Result<Vec<i64>, DivisionError> { - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - let numbers = [27, 297, 38502, 81]; - let division_results = numbers.into_iter().map(|n| divide(n, 27)); - // Collects to the expected return type. Returns the first error in the - // division results (if one exists). - division_results.collect() -} - -fn list_of_results() -> Vec<Result<i64, DivisionError>> { - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - let numbers = [27, 297, 38502, 81]; - let division_results = numbers.into_iter().map(|n| divide(n, 27)); - // Collects to the expected return type. - division_results.collect() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_success() { - assert_eq!(divide(81, 9), Ok(9)); - assert_eq!(divide(81, -1), Ok(-81)); - assert_eq!(divide(i64::MIN, i64::MIN), Ok(1)); - } - - #[test] - fn test_divide_by_0() { - assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero)); - } - - #[test] - fn test_integer_overflow() { - assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow)); - } - - #[test] - fn test_not_divisible() { - assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible)); - } - - #[test] - fn test_divide_0_by_something() { - assert_eq!(divide(0, 81), Ok(0)); - } - - #[test] - fn test_result_with_list() { - assert_eq!(result_with_list().unwrap(), [1, 11, 1426, 3]); - } - - #[test] - fn test_list_of_results() { - assert_eq!(list_of_results(), [Ok(1), Ok(11), Ok(1426), Ok(3)]); - } -} diff --git a/rustlings/solutions/18_iterators/iterators4.rs b/rustlings/solutions/18_iterators/iterators4.rs deleted file mode 100644 index 4168835..0000000 --- a/rustlings/solutions/18_iterators/iterators4.rs +++ /dev/null @@ -1,72 +0,0 @@ -// 3 possible solutions are presented. - -// With `for` loop and a mutable variable. -fn factorial_for(num: u64) -> u64 { - let mut result = 1; - - for x in 2..=num { - result *= x; - } - - result -} - -// Equivalent to `factorial_for` but shorter and without a `for` loop and -// mutable variables. -fn factorial_fold(num: u64) -> u64 { - // Case num==0: The iterator 2..=0 is empty - // -> The initial value of `fold` is returned which is 1. - // Case num==1: The iterator 2..=1 is also empty - // -> The initial value 1 is returned. - // Case num==2: The iterator 2..=2 contains one element - // -> The initial value 1 is multiplied by 2 and the result - // is returned. - // Case num==3: The iterator 2..=3 contains 2 elements - // -> 1 * 2 is calculated, then the result 2 is multiplied by - // the second element 3 so the result 6 is returned. - // And so on… - #[allow(clippy::unnecessary_fold)] - (2..=num).fold(1, |acc, x| acc * x) -} - -// Equivalent to `factorial_fold` but with a built-in method that is suggested -// by Clippy. -fn factorial_product(num: u64) -> u64 { - (2..=num).product() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn factorial_of_0() { - assert_eq!(factorial_for(0), 1); - assert_eq!(factorial_fold(0), 1); - assert_eq!(factorial_product(0), 1); - } - - #[test] - fn factorial_of_1() { - assert_eq!(factorial_for(1), 1); - assert_eq!(factorial_fold(1), 1); - assert_eq!(factorial_product(1), 1); - } - #[test] - fn factorial_of_2() { - assert_eq!(factorial_for(2), 2); - assert_eq!(factorial_fold(2), 2); - assert_eq!(factorial_product(2), 2); - } - - #[test] - fn factorial_of_4() { - assert_eq!(factorial_for(4), 24); - assert_eq!(factorial_fold(4), 24); - assert_eq!(factorial_product(4), 24); - } -} diff --git a/rustlings/solutions/18_iterators/iterators5.rs b/rustlings/solutions/18_iterators/iterators5.rs deleted file mode 100644 index 067a117..0000000 --- a/rustlings/solutions/18_iterators/iterators5.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Let's define a simple model to track Rustlings' exercise progress. Progress -// will be modelled using a hash map. The name of the exercise is the key and -// the progress is the value. Two counting functions were created to count the -// number of exercises with a given progress. Recreate this counting -// functionality using iterators. Try to not use imperative loops (for/while). - -use std::collections::HashMap; - -#[derive(Clone, Copy, PartialEq, Eq)] -enum Progress { - None, - Some, - Complete, -} - -fn count_for(map: &HashMap<String, Progress>, value: Progress) -> usize { - let mut count = 0; - for val in map.values() { - if *val == value { - count += 1; - } - } - count -} - -fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize { - // `map` is a hash map with `String` keys and `Progress` values. - // map = { "variables1": Complete, "from_str": None, … } - map.values().filter(|val| **val == value).count() -} - -fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progress) -> usize { - let mut count = 0; - for map in collection { - count += count_for(map, value); - } - count -} - -fn count_collection_iterator(collection: &[HashMap<String, Progress>], value: Progress) -> usize { - // `collection` is a slice of hash maps. - // collection = [{ "variables1": Complete, "from_str": None, … }, - // { "variables2": Complete, … }, … ] - collection - .iter() - .map(|map| count_iterator(map, value)) - .sum() -} - -// Equivalent to `count_collection_iterator` and `count_iterator`, iterating as -// if the collection was a single container instead of a container of containers -// (and more accurately, a single iterator instead of an iterator of iterators). -fn count_collection_iterator_flat( - collection: &[HashMap<String, Progress>], - value: Progress, -) -> usize { - // `collection` is a slice of hash maps. - // collection = [{ "variables1": Complete, "from_str": None, … }, - // { "variables2": Complete, … }, … ] - collection - .iter() - .flat_map(HashMap::values) // or just `.flatten()` when wanting the default iterator (`HashMap::iter`) - .filter(|val| **val == value) - .count() -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - use Progress::*; - - fn get_map() -> HashMap<String, Progress> { - let mut map = HashMap::new(); - map.insert(String::from("variables1"), Complete); - map.insert(String::from("functions1"), Complete); - map.insert(String::from("hashmap1"), Complete); - map.insert(String::from("arc1"), Some); - map.insert(String::from("as_ref_mut"), None); - map.insert(String::from("from_str"), None); - - map - } - - fn get_vec_map() -> Vec<HashMap<String, Progress>> { - let map = get_map(); - - let mut other = HashMap::new(); - other.insert(String::from("variables2"), Complete); - other.insert(String::from("functions2"), Complete); - other.insert(String::from("if1"), Complete); - other.insert(String::from("from_into"), None); - other.insert(String::from("try_from_into"), None); - - vec![map, other] - } - - #[test] - fn count_complete() { - let map = get_map(); - assert_eq!(count_iterator(&map, Complete), 3); - } - - #[test] - fn count_some() { - let map = get_map(); - assert_eq!(count_iterator(&map, Some), 1); - } - - #[test] - fn count_none() { - let map = get_map(); - assert_eq!(count_iterator(&map, None), 2); - } - - #[test] - fn count_complete_equals_for() { - let map = get_map(); - let progress_states = [Complete, Some, None]; - for progress_state in progress_states { - assert_eq!( - count_for(&map, progress_state), - count_iterator(&map, progress_state), - ); - } - } - - #[test] - fn count_collection_complete() { - let collection = get_vec_map(); - assert_eq!(count_collection_iterator(&collection, Complete), 6); - assert_eq!(count_collection_iterator_flat(&collection, Complete), 6); - } - - #[test] - fn count_collection_some() { - let collection = get_vec_map(); - assert_eq!(count_collection_iterator(&collection, Some), 1); - assert_eq!(count_collection_iterator_flat(&collection, Some), 1); - } - - #[test] - fn count_collection_none() { - let collection = get_vec_map(); - assert_eq!(count_collection_iterator(&collection, None), 4); - assert_eq!(count_collection_iterator_flat(&collection, None), 4); - } - - #[test] - fn count_collection_equals_for() { - let collection = get_vec_map(); - let progress_states = [Complete, Some, None]; - - for progress_state in progress_states { - assert_eq!( - count_collection_for(&collection, progress_state), - count_collection_iterator(&collection, progress_state), - ); - assert_eq!( - count_collection_for(&collection, progress_state), - count_collection_iterator_flat(&collection, progress_state), - ); - } - } -} diff --git a/rustlings/solutions/19_smart_pointers/arc1.rs b/rustlings/solutions/19_smart_pointers/arc1.rs deleted file mode 100644 index bd76189..0000000 --- a/rustlings/solutions/19_smart_pointers/arc1.rs +++ /dev/null @@ -1,45 +0,0 @@ -// In this exercise, we are given a `Vec` of `u32` called `numbers` with values -// ranging from 0 to 99. We would like to use this set of numbers within 8 -// different threads simultaneously. Each thread is going to get the sum of -// every eighth value with an offset. -// -// The first thread (offset 0), will sum 0, 8, 16, … -// The second thread (offset 1), will sum 1, 9, 17, … -// The third thread (offset 2), will sum 2, 10, 18, … -// … -// The eighth thread (offset 7), will sum 7, 15, 23, … -// -// Each thread should own a reference-counting pointer to the vector of -// numbers. But `Rc` isn't thread-safe. Therefore, we need to use `Arc`. -// -// Don't get distracted by how threads are spawned and joined. We will practice -// that later in the exercises about threads. - -// Don't change the lines below. -#![forbid(unused_imports)] -use std::{sync::Arc, thread}; - -fn main() { - let numbers: Vec<_> = (0..100u32).collect(); - - let shared_numbers = Arc::new(numbers); - // ^^^^^^^^^^^^^^^^^ - - let mut join_handles = Vec::new(); - - for offset in 0..8 { - let child_numbers = Arc::clone(&shared_numbers); - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - let handle = thread::spawn(move || { - let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum(); - println!("Sum of offset {offset} is {sum}"); - }); - - join_handles.push(handle); - } - - for handle in join_handles.into_iter() { - handle.join().unwrap(); - } -} diff --git a/rustlings/solutions/19_smart_pointers/box1.rs b/rustlings/solutions/19_smart_pointers/box1.rs deleted file mode 100644 index 189cc56..0000000 --- a/rustlings/solutions/19_smart_pointers/box1.rs +++ /dev/null @@ -1,47 +0,0 @@ -// At compile time, Rust needs to know how much space a type takes up. This -// becomes problematic for recursive types, where a value can have as part of -// itself another value of the same type. To get around the issue, we can use a -// `Box` - a smart pointer used to store data on the heap, which also allows us -// to wrap a recursive type. -// -// The recursive type we're implementing in this exercise is the "cons list", a -// data structure frequently found in functional programming languages. Each -// item in a cons list contains two elements: The value of the current item and -// the next item. The last item is a value called `Nil`. - -#[derive(PartialEq, Debug)] -enum List { - Cons(i32, Box<List>), - Nil, -} - -fn create_empty_list() -> List { - List::Nil -} - -fn create_non_empty_list() -> List { - List::Cons(42, Box::new(List::Nil)) -} - -fn main() { - println!("This is an empty cons list: {:?}", create_empty_list()); - println!( - "This is a non-empty cons list: {:?}", - create_non_empty_list(), - ); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_create_empty_list() { - assert_eq!(create_empty_list(), List::Nil); - } - - #[test] - fn test_create_non_empty_list() { - assert_ne!(create_empty_list(), create_non_empty_list()); - } -} diff --git a/rustlings/solutions/19_smart_pointers/cow1.rs b/rustlings/solutions/19_smart_pointers/cow1.rs deleted file mode 100644 index 461143b..0000000 --- a/rustlings/solutions/19_smart_pointers/cow1.rs +++ /dev/null @@ -1,69 +0,0 @@ -// This exercise explores the `Cow` (Clone-On-Write) smart pointer. It can -// enclose and provide immutable access to borrowed data and clone the data -// lazily when mutation or ownership is required. The type is designed to work -// with general borrowed data via the `Borrow` trait. - -use std::borrow::Cow; - -fn abs_all(input: &mut Cow<[i32]>) { - for ind in 0..input.len() { - let value = input[ind]; - if value < 0 { - // Clones into a vector if not already owned. - input.to_mut()[ind] = -value; - } - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn reference_mutation() { - // Clone occurs because `input` needs to be mutated. - let vec = vec![-1, 0, 1]; - let mut input = Cow::from(&vec); - abs_all(&mut input); - assert!(matches!(input, Cow::Owned(_))); - } - - #[test] - fn reference_no_mutation() { - // No clone occurs because `input` doesn't need to be mutated. - let vec = vec![0, 1, 2]; - let mut input = Cow::from(&vec); - abs_all(&mut input); - assert!(matches!(input, Cow::Borrowed(_))); - // ^^^^^^^^^^^^^^^^ - } - - #[test] - fn owned_no_mutation() { - // We can also pass `vec` without `&` so `Cow` owns it directly. In this - // case, no mutation occurs (all numbers are already absolute) and thus - // also no clone. But the result is still owned because it was never - // borrowed or mutated. - let vec = vec![0, 1, 2]; - let mut input = Cow::from(vec); - abs_all(&mut input); - assert!(matches!(input, Cow::Owned(_))); - // ^^^^^^^^^^^^^ - } - - #[test] - fn owned_mutation() { - // Of course this is also the case if a mutation does occur (not all - // numbers are absolute). In this case, the call to `to_mut()` in the - // `abs_all` function returns a reference to the same data as before. - let vec = vec![-1, 0, 1]; - let mut input = Cow::from(vec); - abs_all(&mut input); - assert!(matches!(input, Cow::Owned(_))); - // ^^^^^^^^^^^^^ - } -} diff --git a/rustlings/solutions/19_smart_pointers/rc1.rs b/rustlings/solutions/19_smart_pointers/rc1.rs deleted file mode 100644 index edf40eb..0000000 --- a/rustlings/solutions/19_smart_pointers/rc1.rs +++ /dev/null @@ -1,102 +0,0 @@ -// In this exercise, we want to express the concept of multiple owners via the -// `Rc<T>` type. This is a model of our solar system - there is a `Sun` type and -// multiple `Planet`s. The planets take ownership of the sun, indicating that -// they revolve around the sun. - -use std::rc::Rc; - -#[derive(Debug)] -struct Sun; - -#[derive(Debug)] -enum Planet { - Mercury(Rc<Sun>), - Venus(Rc<Sun>), - Earth(Rc<Sun>), - Mars(Rc<Sun>), - Jupiter(Rc<Sun>), - Saturn(Rc<Sun>), - Uranus(Rc<Sun>), - Neptune(Rc<Sun>), -} - -impl Planet { - fn details(&self) { - println!("Hi from {self:?}!"); - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn rc1() { - let sun = Rc::new(Sun); - println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference - - let mercury = Planet::Mercury(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 2 references - mercury.details(); - - let venus = Planet::Venus(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 3 references - venus.details(); - - let earth = Planet::Earth(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 4 references - earth.details(); - - let mars = Planet::Mars(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 5 references - mars.details(); - - let jupiter = Planet::Jupiter(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 6 references - jupiter.details(); - - let saturn = Planet::Saturn(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 7 references - saturn.details(); - - let uranus = Planet::Uranus(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 8 references - uranus.details(); - - let neptune = Planet::Neptune(Rc::clone(&sun)); - println!("reference count = {}", Rc::strong_count(&sun)); // 9 references - neptune.details(); - - assert_eq!(Rc::strong_count(&sun), 9); - - drop(neptune); - println!("reference count = {}", Rc::strong_count(&sun)); // 8 references - - drop(uranus); - println!("reference count = {}", Rc::strong_count(&sun)); // 7 references - - drop(saturn); - println!("reference count = {}", Rc::strong_count(&sun)); // 6 references - - drop(jupiter); - println!("reference count = {}", Rc::strong_count(&sun)); // 5 references - - drop(mars); - println!("reference count = {}", Rc::strong_count(&sun)); // 4 references - - drop(earth); - println!("reference count = {}", Rc::strong_count(&sun)); // 3 references - - drop(venus); - println!("reference count = {}", Rc::strong_count(&sun)); // 2 references - - drop(mercury); - println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference - - assert_eq!(Rc::strong_count(&sun), 1); - } -} diff --git a/rustlings/solutions/20_threads/threads1.rs b/rustlings/solutions/20_threads/threads1.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/20_threads/threads1.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/20_threads/threads2.rs b/rustlings/solutions/20_threads/threads2.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/20_threads/threads2.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/20_threads/threads3.rs b/rustlings/solutions/20_threads/threads3.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/20_threads/threads3.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/21_macros/macros1.rs b/rustlings/solutions/21_macros/macros1.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/21_macros/macros1.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/21_macros/macros2.rs b/rustlings/solutions/21_macros/macros2.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/21_macros/macros2.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/21_macros/macros3.rs b/rustlings/solutions/21_macros/macros3.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/21_macros/macros3.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/21_macros/macros4.rs b/rustlings/solutions/21_macros/macros4.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/21_macros/macros4.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/22_clippy/clippy1.rs b/rustlings/solutions/22_clippy/clippy1.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/22_clippy/clippy1.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/22_clippy/clippy2.rs b/rustlings/solutions/22_clippy/clippy2.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/22_clippy/clippy2.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/22_clippy/clippy3.rs b/rustlings/solutions/22_clippy/clippy3.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/22_clippy/clippy3.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/23_conversions/as_ref_mut.rs b/rustlings/solutions/23_conversions/as_ref_mut.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/23_conversions/as_ref_mut.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/23_conversions/from_into.rs b/rustlings/solutions/23_conversions/from_into.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/23_conversions/from_into.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/23_conversions/from_str.rs b/rustlings/solutions/23_conversions/from_str.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/23_conversions/from_str.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/23_conversions/try_from_into.rs b/rustlings/solutions/23_conversions/try_from_into.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/23_conversions/try_from_into.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/23_conversions/using_as.rs b/rustlings/solutions/23_conversions/using_as.rs deleted file mode 100644 index dcf2377..0000000 --- a/rustlings/solutions/23_conversions/using_as.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - // DON'T EDIT THIS SOLUTION FILE! - // It will be automatically filled after you finish the exercise. -} diff --git a/rustlings/solutions/README.md b/rustlings/solutions/README.md deleted file mode 100644 index 5b5176b..0000000 --- a/rustlings/solutions/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Official Rustlings solutions - -Before you finish an exercise, its solution file will only contain an empty `main` function. -The content of this file will be automatically replaced by the actual solution once you finish the exercise. - -Note that these solutions are often only _one possibility_ to solve an exercise. diff --git a/rustlings/solutions/quizzes/quiz1.rs b/rustlings/solutions/quizzes/quiz1.rs deleted file mode 100644 index 5503c8c..0000000 --- a/rustlings/solutions/quizzes/quiz1.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Mary is buying apples. The price of an apple is calculated as follows: -// - An apple costs 2 rustbucks. -// - However, if Mary buys more than 40 apples, the price of each apple in the -// entire order is reduced to only 1 rustbuck! - -fn calculate_price_of_apples(n_apples: u64) -> u64 { - if n_apples > 40 { - n_apples - } else { - 2 * n_apples - } -} - -fn main() { - // You can optionally experiment here. -} - -// Don't change the tests! -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn verify_test() { - assert_eq!(calculate_price_of_apples(35), 70); - assert_eq!(calculate_price_of_apples(40), 80); - assert_eq!(calculate_price_of_apples(41), 41); - assert_eq!(calculate_price_of_apples(65), 65); - } -} diff --git a/rustlings/solutions/quizzes/quiz2.rs b/rustlings/solutions/quizzes/quiz2.rs deleted file mode 100644 index 8b073b1..0000000 --- a/rustlings/solutions/quizzes/quiz2.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Let's build a little machine in the form of a function. As input, we're going -// to give a list of strings and commands. These commands determine what action -// is going to be applied to the string. It can either be: -// - Uppercase the string -// - Trim the string -// - Append "bar" to the string a specified amount of times -// -// The exact form of this will be: -// - The input is going to be a vector of 2-length tuples, -// the first element is the string, the second one is the command. -// - The output element is going to be a vector of strings. - -enum Command { - Uppercase, - Trim, - Append(usize), -} - -mod my_module { - use super::Command; - - // The solution with a loop. Check out `transformer_iter` for a version - // with iterators. - pub fn transformer(input: Vec<(String, Command)>) -> Vec<String> { - let mut output = Vec::new(); - - for (string, command) in input { - // Create the new string. - let new_string = match command { - Command::Uppercase => string.to_uppercase(), - Command::Trim => string.trim().to_string(), - Command::Append(n) => string + &"bar".repeat(n), - }; - - // Push the new string to the output vector. - output.push(new_string); - } - - output - } - - // Equivalent to `transform` but uses an iterator instead of a loop for - // comparison. Don't worry, we will practice iterators later ;) - pub fn transformer_iter(input: Vec<(String, Command)>) -> Vec<String> { - input - .into_iter() - .map(|(string, command)| match command { - Command::Uppercase => string.to_uppercase(), - Command::Trim => string.trim().to_string(), - Command::Append(n) => string + &"bar".repeat(n), - }) - .collect() - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - // Import `transformer`. - use super::my_module::transformer; - - use super::Command; - use super::my_module::transformer_iter; - - #[test] - fn it_works() { - for transformer in [transformer, transformer_iter] { - let input = vec![ - ("hello".to_string(), Command::Uppercase), - (" all roads lead to rome! ".to_string(), Command::Trim), - ("foo".to_string(), Command::Append(1)), - ("bar".to_string(), Command::Append(5)), - ]; - let output = transformer(input); - - assert_eq!( - output, - [ - "HELLO", - "all roads lead to rome!", - "foobar", - "barbarbarbarbarbar", - ] - ); - } - } -} diff --git a/rustlings/solutions/quizzes/quiz3.rs b/rustlings/solutions/quizzes/quiz3.rs deleted file mode 100644 index 7b91278..0000000 --- a/rustlings/solutions/quizzes/quiz3.rs +++ /dev/null @@ -1,65 +0,0 @@ -// An imaginary magical school has a new report card generation system written -// in Rust! Currently, the system only supports creating report cards where the -// student's grade is represented numerically (e.g. 1.0 -> 5.5). However, the -// school also issues alphabetical grades (A+ -> F-) and needs to be able to -// print both types of report card! -// -// Make the necessary code changes in the struct `ReportCard` and the impl -// block to support alphabetical report cards in addition to numerical ones. - -use std::fmt::Display; - -// Make the struct generic over `T`. -struct ReportCard<T> { - // ^^^ - grade: T, - // ^ - student_name: String, - student_age: u8, -} - -// To be able to print the grade, it has to implement the `Display` trait. -impl<T: Display> ReportCard<T> { - // ^^^^^^^ require that `T` implements `Display`. - fn print(&self) -> String { - format!( - "{} ({}) - achieved a grade of {}", - &self.student_name, &self.student_age, &self.grade, - ) - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn generate_numeric_report_card() { - let report_card = ReportCard { - grade: 2.1, - student_name: "Tom Wriggle".to_string(), - student_age: 12, - }; - assert_eq!( - report_card.print(), - "Tom Wriggle (12) - achieved a grade of 2.1", - ); - } - - #[test] - fn generate_alphabetic_report_card() { - let report_card = ReportCard { - grade: "A+", - student_name: "Gary Plotter".to_string(), - student_age: 11, - }; - assert_eq!( - report_card.print(), - "Gary Plotter (11) - achieved a grade of A+", - ); - } -} |