├── Codeforces ICPC Assiut University Community └── A. Winter Sale.rs ├── README.md └── Rustlings ├── 00_intro ├── README.md ├── intro1.rs └── intro2.rs ├── 01_variables ├── README.md ├── variables1.rs ├── variables2.rs ├── variables3.rs ├── variables4.rs ├── variables5.rs └── variables6.rs ├── 02_functions ├── README.md ├── functions1.rs ├── functions2.rs ├── functions3.rs ├── functions4.rs └── functions5.rs ├── 03_if ├── README.md ├── if1.rs ├── if2.rs └── if3.rs ├── 04_primitive_types ├── README.md ├── primitive_types1.rs ├── primitive_types2.rs ├── primitive_types3.rs ├── primitive_types4.rs ├── primitive_types5.rs └── primitive_types6.rs ├── 05_vecs ├── README.md ├── vecs1.rs └── vecs2.rs ├── 06_move_semantics ├── README.md ├── move_semantics1.rs ├── move_semantics2.rs ├── move_semantics3.rs ├── move_semantics4.rs └── move_semantics5.rs ├── 07_structs ├── README.md ├── structs1.rs ├── structs2.rs └── structs3.rs ├── 08_enums ├── README.md ├── enums1.rs ├── enums2.rs └── enums3.rs ├── 09_strings ├── README.md ├── strings1.rs ├── strings2.rs ├── strings3.rs └── strings4.rs ├── 10_modules ├── README.md ├── modules1.rs ├── modules2.rs └── modules3.rs ├── 11_hashmaps ├── README.md ├── hashmaps1.rs ├── hashmaps2.rs └── hashmaps3.rs ├── 12_options ├── README.md ├── options1.rs ├── options2.rs └── options3.rs ├── 13_error_handling ├── README.md ├── errors1.rs ├── errors2.rs ├── errors3.rs ├── errors4.rs ├── errors5.rs └── errors6.rs ├── 14_generics ├── README.md ├── generics1.rs └── generics2.rs ├── 15_traits ├── README.md ├── traits1.rs ├── traits2.rs ├── traits3.rs ├── traits4.rs └── traits5.rs ├── 16_lifetimes ├── README.md ├── lifetimes1.rs ├── lifetimes2.rs └── lifetimes3.rs ├── 17_tests ├── README.md ├── tests1.rs ├── tests2.rs └── tests3.rs ├── 18_iterators ├── README.md ├── iterators1.rs ├── iterators2.rs ├── iterators3.rs ├── iterators4.rs └── iterators5.rs └── quizzes ├── README.md ├── quiz1.rs ├── quiz2.rs └── quiz3.rs /Codeforces ICPC Assiut University Community/A. Winter Sale.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | fn main() { 4 | let mut num1: String = String::new(); 5 | 6 | io::stdin().read_line(&mut num1).expect("Error"); 7 | 8 | let parts: Vec<&str> = num1.trim().split_whitespace().collect(); 9 | let mut num1: i64 = parts[0].parse::().expect("Error"); 10 | let mut num2: i64 = parts[1].parse::().expect("Error"); 11 | num2 = num2 * 100; 12 | num1 = 100 - num1; 13 | let ans: f32 = num2 as f32 / num1 as f32; 14 | println!("{:.2}", ans); 15 | } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learn-Rust 2 | 3 | This repo is about me learning and practicing rust 4 | -------------------------------------------------------------------------------- /Rustlings/00_intro/README.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | Rust uses the `print!` and `println!` macros to print text to the console. 4 | 5 | ## Further information 6 | 7 | - [Hello World](https://doc.rust-lang.org/rust-by-example/hello.html) 8 | - [Formatted print](https://doc.rust-lang.org/rust-by-example/hello/print.html) 9 | -------------------------------------------------------------------------------- /Rustlings/00_intro/intro1.rs: -------------------------------------------------------------------------------- 1 | // TODO: We sometimes encourage you to keep trying things on a given exercise 2 | // even after you already figured it out. If you got everything working and feel 3 | // ready for the next exercise, enter `n` in the terminal. 4 | // 5 | // The exercise file will be reloaded when you change one of the lines below! 6 | // Try adding a new `println!` and check the updated output in the terminal. 7 | 8 | fn main() { 9 | println!(r#" Welcome to... "#); 10 | println!(r#" _ _ _ "#); 11 | println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); 12 | println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); 13 | println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); 14 | println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); 15 | println!(r#" |___/ "#); 16 | println!(); 17 | println!("This exercise compiles successfully. The remaining exercises contain a compiler"); 18 | println!("or logic error. The central concept behind Rustlings is to fix these errors and"); 19 | println!("solve the exercises. Good luck!"); 20 | println!(); 21 | println!("The file of this exercise is `exercises/00_intro/intro1.rs`. Have a look!"); 22 | println!("The current exercise path will be always shown under the progress bar."); 23 | println!("You can click on the path to open the exercise file in your editor."); 24 | } 25 | -------------------------------------------------------------------------------- /Rustlings/00_intro/intro2.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // TODO: Fix the code to print "Hello world!". 3 | println!("Hello world!"); 4 | } 5 | -------------------------------------------------------------------------------- /Rustlings/01_variables/README.md: -------------------------------------------------------------------------------- 1 | # Variables 2 | 3 | In Rust, variables are immutable by default. 4 | When a variable is immutable, once a value is bound to a name, you can’t change that value. 5 | You can make them mutable by adding `mut` in front of the variable name. 6 | 7 | ## Further information 8 | 9 | - [Variables and Mutability](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html) 10 | -------------------------------------------------------------------------------- /Rustlings/01_variables/variables1.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // TODO: Add the missing keyword. 3 | let x = 5; 4 | 5 | println!("x has the value {x}"); 6 | } 7 | -------------------------------------------------------------------------------- /Rustlings/01_variables/variables2.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // TODO: Change the line below to fix the compiler error. 3 | let x = 10; 4 | 5 | if x == 10 { 6 | println!("x is ten!"); 7 | } else { 8 | println!("x is not ten!"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Rustlings/01_variables/variables3.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // TODO: Change the line below to fix the compiler error. 3 | let x: i32=10; 4 | 5 | println!("Number {x}"); 6 | } 7 | -------------------------------------------------------------------------------- /Rustlings/01_variables/variables4.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error. 2 | fn main() { 3 | let mut x = 3; 4 | println!("Number {x}"); 5 | 6 | x = 5; // Don't change this line 7 | println!("Number {x}"); 8 | } 9 | -------------------------------------------------------------------------------- /Rustlings/01_variables/variables5.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let number = "T-H-R-E-E"; // Don't change this line 3 | println!("Spell a number: {}", number); 4 | 5 | // TODO: Fix the compiler error by changing the line below without renaming the variable. 6 | let number = 3; 7 | println!("Number plus two is: {}", number + 2); 8 | } 9 | -------------------------------------------------------------------------------- /Rustlings/01_variables/variables6.rs: -------------------------------------------------------------------------------- 1 | // TODO: Change the line below to fix the compiler error. 2 | const NUMBER :i32 = 3; 3 | 4 | fn main() { 5 | println!("Number: {NUMBER}"); 6 | } 7 | -------------------------------------------------------------------------------- /Rustlings/02_functions/README.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | Here, you'll learn how to write functions and how the Rust compiler can help you debug errors even 4 | in more complex code. 5 | 6 | ## Further information 7 | 8 | - [How Functions Work](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html) 9 | -------------------------------------------------------------------------------- /Rustlings/02_functions/functions1.rs: -------------------------------------------------------------------------------- 1 | // TODO: Add some function with the name `call_me` without arguments or a return value. 2 | 3 | fn call_me(){ 4 | } 5 | 6 | fn main() { 7 | call_me(); // Don't change this line 8 | } 9 | -------------------------------------------------------------------------------- /Rustlings/02_functions/functions2.rs: -------------------------------------------------------------------------------- 1 | // TODO: Add the missing type of the argument `num` after the colon `:`. 2 | fn call_me(num:i32) { 3 | for i in 0..num { 4 | println!("Ring! Call number {}", i + 1); 5 | } 6 | } 7 | 8 | fn main() { 9 | call_me(3); 10 | } 11 | -------------------------------------------------------------------------------- /Rustlings/02_functions/functions3.rs: -------------------------------------------------------------------------------- 1 | fn call_me(num: u8) { 2 | for i in 0..num { 3 | println!("Ring! Call number {}", i + 1); 4 | } 5 | } 6 | 7 | fn main() { 8 | // TODO: Fix the function call. 9 | call_me(5); 10 | } 11 | -------------------------------------------------------------------------------- /Rustlings/02_functions/functions4.rs: -------------------------------------------------------------------------------- 1 | // This store is having a sale where if the price is an even number, you get 10 2 | // Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. 3 | // Don't worry about the function bodies themselves, we are only interested in 4 | // the signatures for now. 5 | 6 | fn is_even(num: i64) -> bool { 7 | num % 2 == 0 8 | } 9 | 10 | // TODO: Fix the function signature. 11 | fn sale_price(price: i64) -> i64{ 12 | if is_even(price) { 13 | price - 10 14 | } else { 15 | price - 3 16 | } 17 | } 18 | 19 | fn main() { 20 | let original_price = 51; 21 | println!("Your sale price is {}", sale_price(original_price)); 22 | } 23 | -------------------------------------------------------------------------------- /Rustlings/02_functions/functions5.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the function body without changing the signature. 2 | fn square(num: i32) -> i32 { 3 | num * num 4 | } 5 | 6 | fn main() { 7 | let answer = square(3); 8 | println!("The square of 3 is {answer}"); 9 | } 10 | -------------------------------------------------------------------------------- /Rustlings/03_if/README.md: -------------------------------------------------------------------------------- 1 | # If 2 | 3 | `if`, the most basic (but still surprisingly versatile!) type of control flow, is what you'll learn here. 4 | 5 | ## Further information 6 | 7 | - [Control Flow - if expressions](https://doc.rust-lang.org/book/ch03-05-control-flow.html#if-expressions) 8 | -------------------------------------------------------------------------------- /Rustlings/03_if/if1.rs: -------------------------------------------------------------------------------- 1 | fn bigger(a: i32, b: i32) -> i32 { 2 | // TODO: Complete this function to return the bigger number! 3 | // If both numbers are equal, any of them can be returned. 4 | // Do not use: 5 | // - another function call 6 | // - additional variables 7 | if a > b { 8 | a 9 | }else { 10 | b 11 | } 12 | } 13 | 14 | fn main() { 15 | // You can optionally experiment here. 16 | } 17 | 18 | // Don't mind this for now :) 19 | #[cfg(test)] 20 | mod tests { 21 | use super::*; 22 | 23 | #[test] 24 | fn ten_is_bigger_than_eight() { 25 | assert_eq!(10, bigger(10, 8)); 26 | } 27 | 28 | #[test] 29 | fn fortytwo_is_bigger_than_thirtytwo() { 30 | assert_eq!(42, bigger(32, 42)); 31 | } 32 | 33 | #[test] 34 | fn equal_numbers() { 35 | assert_eq!(42, bigger(42, 42)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Rustlings/03_if/if2.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error on this function. 2 | fn foo_if_fizz(fizzish: &str) -> &str { 3 | if fizzish == "fizz" { 4 | "foo" 5 | } 6 | else if fizzish == "fuzz"{ 7 | "bar" 8 | } 9 | else { 10 | "baz" 11 | } 12 | } 13 | 14 | fn main() { 15 | // You can optionally experiment here. 16 | } 17 | 18 | // TODO: Read the tests to understand the desired behavior. 19 | // Make all tests pass without changing them. 20 | #[cfg(test)] 21 | mod tests { 22 | use super::*; 23 | 24 | #[test] 25 | fn foo_for_fizz() { 26 | // This means that calling `foo_if_fizz` with the argument "fizz" should return "foo". 27 | assert_eq!(foo_if_fizz("fizz"), "foo"); 28 | } 29 | 30 | #[test] 31 | fn bar_for_fuzz() { 32 | assert_eq!(foo_if_fizz("fuzz"), "bar"); 33 | } 34 | 35 | #[test] 36 | fn default_to_baz() { 37 | assert_eq!(foo_if_fizz("literally anything"), "baz"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Rustlings/03_if/if3.rs: -------------------------------------------------------------------------------- 1 | fn animal_habitat(animal: &str) -> &str { 2 | // TODO: Fix the compiler error in the statement below. 3 | let identifier = if animal == "crab" { 4 | 1 5 | } else if animal == "gopher" { 6 | 2 7 | } else if animal == "snake" { 8 | 3 9 | } else { 10 | 999 11 | }; 12 | 13 | // Don't change the expression below! 14 | if identifier == 1 { 15 | "Beach" 16 | } else if identifier == 2 { 17 | "Burrow" 18 | } else if identifier == 3 { 19 | "Desert" 20 | } else { 21 | "Unknown" 22 | } 23 | } 24 | 25 | fn main() { 26 | // You can optionally experiment here. 27 | } 28 | 29 | // Don't change the tests! 30 | #[cfg(test)] 31 | mod tests { 32 | use super::*; 33 | 34 | #[test] 35 | fn gopher_lives_in_burrow() { 36 | assert_eq!(animal_habitat("gopher"), "Burrow") 37 | } 38 | 39 | #[test] 40 | fn snake_lives_in_desert() { 41 | assert_eq!(animal_habitat("snake"), "Desert") 42 | } 43 | 44 | #[test] 45 | fn crab_lives_on_beach() { 46 | assert_eq!(animal_habitat("crab"), "Beach") 47 | } 48 | 49 | #[test] 50 | fn unknown_animal() { 51 | assert_eq!(animal_habitat("dinosaur"), "Unknown") 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/README.md: -------------------------------------------------------------------------------- 1 | # Primitive Types 2 | 3 | Rust has a couple of basic types that are directly implemented into the 4 | compiler. In this section, we'll go through the most important ones. 5 | 6 | ## Further information 7 | 8 | - [Data Types](https://doc.rust-lang.org/book/ch03-02-data-types.html) 9 | - [The Slice Type](https://doc.rust-lang.org/book/ch04-03-slices.html) 10 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/primitive_types1.rs: -------------------------------------------------------------------------------- 1 | // Booleans (`bool`) 2 | 3 | fn main() { 4 | let is_morning = true; 5 | if is_morning { 6 | println!("Good morning!"); 7 | } 8 | 9 | // TODO: Define a boolean variable with the name `is_evening` before the `if` statement below. 10 | // The value of the variable should be the negation (opposite) of `is_morning`. 11 | // let … 12 | let is_evening:bool = true; 13 | if is_evening { 14 | println!("Good evening!"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/primitive_types2.rs: -------------------------------------------------------------------------------- 1 | // Characters (`char`) 2 | 3 | fn main() { 4 | // Note the _single_ quotes, these are different from the double quotes 5 | // you've been seeing around. 6 | let my_first_initial = 'C'; 7 | if my_first_initial.is_alphabetic() { 8 | println!("Alphabetical!"); 9 | } else if my_first_initial.is_numeric() { 10 | println!("Numerical!"); 11 | } else { 12 | println!("Neither alphabetic nor numeric!"); 13 | } 14 | 15 | // TODO: Analogous to the example before, declare a variable called `your_character` 16 | // below with your favorite character. 17 | // Try a letter, try a digit (in single quotes), try a special character, try a character 18 | // from a different language than your own, try an emoji 😉 19 | // let your_character = ''; 20 | let your_character = '1'; 21 | if your_character.is_alphabetic() { 22 | println!("Alphabetical!"); 23 | } else if your_character.is_numeric() { 24 | println!("Numerical!"); 25 | } else { 26 | println!("Neither alphabetic nor numeric!"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/primitive_types3.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // TODO: Create an array called `a` with at least 100 elements in it. 3 | // let a = ??? 4 | let a = [0;100]; 5 | 6 | if a.len() >= 100 { 7 | println!("Wow, that's a big array!"); 8 | } else { 9 | println!("Meh, I eat arrays like that for breakfast."); 10 | panic!("Array not big enough, more elements needed"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/primitive_types4.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // You can optionally experiment here. 3 | } 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | #[test] 8 | fn slice_out_of_array() { 9 | let a = [1, 2, 3, 4, 5]; 10 | 11 | // TODO: Get a slice called `nice_slice` out of the array `a` so that the test passes. 12 | // let nice_slice = ??? 13 | let nice_slice = &a[1..4]; 14 | 15 | assert_eq!([2, 3, 4], nice_slice); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/primitive_types5.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let cat = ("Furry McFurson", 3.5); 3 | 4 | // TODO: Destructure the `cat` tuple in one statement so that the println works. 5 | // let /* your pattern here */ = cat; 6 | let (name,age) = cat; 7 | 8 | println!("{name} is {age} years old"); 9 | } 10 | -------------------------------------------------------------------------------- /Rustlings/04_primitive_types/primitive_types6.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // You can optionally experiment here. 3 | } 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | #[test] 8 | fn indexing_tuple() { 9 | let numbers = (1, 2, 3); 10 | 11 | // TODO: Use a tuple index to access the second element of `numbers` 12 | // and assign it to a variable called `second`. 13 | // let second = ???; 14 | let second = numbers.1; 15 | assert_eq!(second, 2, "This is not the 2nd number in the tuple!"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Rustlings/05_vecs/README.md: -------------------------------------------------------------------------------- 1 | # Vectors 2 | 3 | Vectors are one of the most-used Rust data structures. In other programming 4 | languages, they'd simply be called Arrays, but since Rust operates on a 5 | bit of a lower level, an array in Rust is stored on the stack (meaning it 6 | can't grow or shrink, and the size needs to be known at compile time), 7 | and a Vector is stored in the heap (where these restrictions do not apply). 8 | 9 | Vectors are a bit of a later chapter in the book, but we think that they're 10 | useful enough to talk about them a bit earlier. We shall be talking about 11 | the other useful data structure, hash maps, later. 12 | 13 | ## Further information 14 | 15 | - [Storing Lists of Values with Vectors](https://doc.rust-lang.org/book/ch08-01-vectors.html) 16 | - [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut) 17 | - [`map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map) 18 | -------------------------------------------------------------------------------- /Rustlings/05_vecs/vecs1.rs: -------------------------------------------------------------------------------- 1 | fn array_and_vec() -> ([i32; 4], Vec) { 2 | let a = [10, 20, 30, 40]; // Array 3 | 4 | // TODO: Create a vector called `v` which contains the exact same elements as in the array `a`. 5 | // Use the vector macro. 6 | // let v = ???; 7 | let v = a.to_vec() ; 8 | (a, v) 9 | } 10 | 11 | fn main() { 12 | // You can optionally experiment here. 13 | } 14 | 15 | #[cfg(test)] 16 | mod tests { 17 | use super::*; 18 | 19 | #[test] 20 | fn test_array_and_vec_similarity() { 21 | let (a, v) = array_and_vec(); 22 | assert_eq!(a, *v); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Rustlings/05_vecs/vecs2.rs: -------------------------------------------------------------------------------- 1 | fn vec_loop(input: &[i32]) -> Vec { 2 | let mut output = Vec::new(); 3 | 4 | for element in input { 5 | // TODO: Multiply each element in the `input` slice by 2 and push it to 6 | output.push((*element)*2); 7 | } 8 | 9 | output 10 | } 11 | 12 | fn vec_map_example(input: &[i32]) -> Vec { 13 | // An example of collecting a vector after mapping. 14 | // We map each element of the `input` slice to its value plus 1. 15 | // If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`. 16 | input.iter().map(|element| element + 1).collect() 17 | } 18 | 19 | fn vec_map(input: &[i32]) -> Vec { 20 | // TODO: Here, we also want to multiply each element in the `input` slice 21 | // by 2, but with iterator mapping instead of manually pushing into an empty 22 | // vector. 23 | // See the example in the function `vec_map_example` above. 24 | input 25 | .iter() 26 | .map(|element| { 27 | element*2 28 | }) 29 | .collect() 30 | } 31 | 32 | fn main() { 33 | // You can optionally experiment here. 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn test_vec_loop() { 42 | let input = [2, 4, 6, 8, 10]; 43 | let ans = vec_loop(&input); 44 | assert_eq!(ans, [4, 8, 12, 16, 20]); 45 | } 46 | 47 | #[test] 48 | fn test_vec_map_example() { 49 | let input = [1, 2, 3]; 50 | let ans = vec_map_example(&input); 51 | assert_eq!(ans, [2, 3, 4]); 52 | } 53 | 54 | #[test] 55 | fn test_vec_map() { 56 | let input = [2, 4, 6, 8, 10]; 57 | let ans = vec_map(&input); 58 | assert_eq!(ans, [4, 8, 12, 16, 20]); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Rustlings/06_move_semantics/README.md: -------------------------------------------------------------------------------- 1 | # Move Semantics 2 | 3 | These exercises are adapted from [pnkfelix](https://github.com/pnkfelix)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!! 4 | 5 | ## Further information 6 | 7 | For this section, the book links are especially important. 8 | 9 | - [Ownership](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html) 10 | - [Reference and borrowing](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html) 11 | -------------------------------------------------------------------------------- /Rustlings/06_move_semantics/move_semantics1.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error in this function. 2 | fn fill_vec(vec: Vec) -> Vec { 3 | let mut vec = vec; 4 | 5 | vec.push(88); 6 | 7 | vec 8 | } 9 | 10 | fn main() { 11 | // You can optionally experiment here. 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn move_semantics1() { 20 | let vec0 = vec![22, 44, 66]; 21 | let vec1 = fill_vec(vec0); 22 | assert_eq!(vec1, vec![22, 44, 66, 88]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Rustlings/06_move_semantics/move_semantics2.rs: -------------------------------------------------------------------------------- 1 | fn fill_vec(vec: Vec) -> Vec { 2 | let mut vec = vec; 3 | 4 | vec.push(88); 5 | 6 | vec 7 | } 8 | 9 | fn main() { 10 | // You can optionally experiment here. 11 | } 12 | 13 | #[cfg(test)] 14 | mod tests { 15 | use super::*; 16 | 17 | // TODO: Make both vectors `vec0` and `vec1` accessible at the same time to 18 | // fix the compiler error in the test. 19 | #[test] 20 | fn move_semantics2() { 21 | let vec0 = vec![22, 44, 66]; 22 | 23 | let vec1 = fill_vec(vec0.clone()); 24 | 25 | assert_eq!(vec0, [22, 44, 66]); 26 | assert_eq!(vec1, [22, 44, 66, 88]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Rustlings/06_move_semantics/move_semantics3.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error in the function without adding any new line. 2 | fn fill_vec(mut vec: Vec) -> Vec { 3 | vec.push(88); 4 | 5 | vec 6 | } 7 | 8 | fn main() { 9 | // You can optionally experiment here. 10 | } 11 | 12 | #[cfg(test)] 13 | mod tests { 14 | use super::*; 15 | 16 | #[test] 17 | fn move_semantics3() { 18 | let vec0 = vec![22, 44, 66]; 19 | let vec1 = fill_vec(vec0); 20 | assert_eq!(vec1, [22, 44, 66, 88]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Rustlings/06_move_semantics/move_semantics4.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // You can optionally experiment here. 3 | } 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | // TODO: Fix the compiler errors only by reordering the lines in the test. 8 | // Don't add, change or remove any line. 9 | #[test] 10 | fn move_semantics4() { 11 | let mut x = Vec::new(); 12 | let y = &mut x; 13 | y.push(42); 14 | let z = &mut x; 15 | z.push(13); 16 | assert_eq!(x, [42, 13]); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Rustlings/06_move_semantics/move_semantics5.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::ptr_arg)] 2 | 3 | // TODO: Fix the compiler errors without changing anything except adding or 4 | // removing references (the character `&`). 5 | 6 | // Shouldn't take ownership 7 | fn get_char(data: &String) -> char { 8 | data.chars().last().unwrap() 9 | } 10 | 11 | // Should take ownership 12 | fn string_uppercase(mut data: String) { 13 | data = data.to_uppercase(); 14 | 15 | println!("{data}"); 16 | } 17 | 18 | fn main() { 19 | let data = "Rust is great!".to_string(); 20 | 21 | get_char(&data); 22 | 23 | string_uppercase(data); 24 | } 25 | -------------------------------------------------------------------------------- /Rustlings/07_structs/README.md: -------------------------------------------------------------------------------- 1 | # Structs 2 | 3 | Rust has three struct types: a classic C struct, a tuple struct, and a unit struct. 4 | 5 | ## Further information 6 | 7 | - [Structures](https://doc.rust-lang.org/book/ch05-01-defining-structs.html) 8 | - [Method Syntax](https://doc.rust-lang.org/book/ch05-03-method-syntax.html) 9 | -------------------------------------------------------------------------------- /Rustlings/07_structs/structs1.rs: -------------------------------------------------------------------------------- 1 | /********************************************************************************************************************* */ 2 | struct ColorRegularStruct { 3 | // TODO: Add the fields that the test `regular_structs` expects. 4 | // What types should the fields have? What are the minimum and maximum values for RGB colors? 5 | red:i32, 6 | green:i32, 7 | blue:i32, 8 | 9 | } 10 | 11 | struct ColorTupleStruct(i32,i32,i32); 12 | 13 | #[derive(Debug)] 14 | struct UnitStruct; 15 | 16 | fn main() { 17 | // You can optionally experiment here. 18 | } 19 | 20 | #[cfg(test)] 21 | mod tests { 22 | use super::*; 23 | 24 | #[test] 25 | fn regular_structs() { 26 | // TODO: Instantiate a regular struct. 27 | // let green = 28 | let green = ColorRegularStruct{ 29 | red:0, 30 | green:255, 31 | blue:0, 32 | }; 33 | 34 | assert_eq!(green.red, 0); 35 | assert_eq!(green.green, 255); 36 | assert_eq!(green.blue, 0); 37 | } 38 | 39 | #[test] 40 | fn tuple_structs() { 41 | // TODO: Instantiate a tuple struct. 42 | // let green = 43 | let green = ColorTupleStruct(0,255,0); 44 | assert_eq!(green.0, 0); 45 | assert_eq!(green.1, 255); 46 | assert_eq!(green.2, 0); 47 | } 48 | 49 | #[test] 50 | fn unit_structs() { 51 | // TODO: Instantiate a unit struct. 52 | // let unit_struct = 53 | let unit_struct = UnitStruct; 54 | let message = format!("{unit_struct:?}s are fun!"); 55 | 56 | assert_eq!(message, "UnitStructs are fun!"); 57 | } 58 | } -------------------------------------------------------------------------------- /Rustlings/07_structs/structs2.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | struct Order { 3 | name: String, 4 | year: u32, 5 | made_by_phone: bool, 6 | made_by_mobile: bool, 7 | made_by_email: bool, 8 | item_number: u32, 9 | count: u32, 10 | } 11 | 12 | fn create_order_template() -> Order { 13 | Order { 14 | name: String::from("Bob"), 15 | year: 2019, 16 | made_by_phone: false, 17 | made_by_mobile: false, 18 | made_by_email: true, 19 | item_number: 123, 20 | count: 0, 21 | } 22 | } 23 | 24 | fn main() { 25 | // You can optionally experiment here. 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn your_order() { 34 | let order_template = create_order_template(); 35 | 36 | // TODO: Create your own order using the update syntax and template above! 37 | // let your_order = 38 | let your_order = Order { 39 | name: String::from("Hacker in Rust"), 40 | year: 2019, 41 | made_by_phone: false, 42 | made_by_mobile: false, 43 | made_by_email: true, 44 | item_number: 123, 45 | count: 1, 46 | }; 47 | assert_eq!(your_order.name, "Hacker in Rust"); 48 | assert_eq!(your_order.year, order_template.year); 49 | assert_eq!(your_order.made_by_phone, order_template.made_by_phone); 50 | assert_eq!(your_order.made_by_mobile, order_template.made_by_mobile); 51 | assert_eq!(your_order.made_by_email, order_template.made_by_email); 52 | assert_eq!(your_order.item_number, order_template.item_number); 53 | assert_eq!(your_order.count, 1); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Rustlings/07_structs/structs3.rs: -------------------------------------------------------------------------------- 1 | // Structs contain data, but can also have logic. In this exercise, we have 2 | // defined the `Package` struct, and we want to test some logic attached to it. 3 | 4 | #[derive(Debug)] 5 | struct Package { 6 | sender_country: String, 7 | recipient_country: String, 8 | weight_in_grams: u32, 9 | } 10 | 11 | impl Package { 12 | fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self { 13 | if weight_in_grams < 10 { 14 | // This isn't how you should handle errors in Rust, but we will 15 | // learn about error handling later. 16 | panic!("Can't ship a package with weight below 10 grams"); 17 | } 18 | 19 | Self { 20 | sender_country, 21 | recipient_country, 22 | weight_in_grams, 23 | } 24 | } 25 | 26 | // TODO: Add the correct return type to the function signature. 27 | fn is_international(&self) -> bool{ 28 | // TODO: Read the tests that use this method to find out when a package 29 | // is considered international. 30 | if self.sender_country != self.recipient_country{ 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | // TODO: Add the correct return type to the function signature. 37 | fn get_fees(&self, cents_per_gram: u32) -> u32{ 38 | // TODO: Calculate the package's fees. 39 | return cents_per_gram*1500; 40 | 41 | } 42 | } 43 | 44 | fn main() { 45 | // You can optionally experiment here. 46 | } 47 | 48 | #[cfg(test)] 49 | mod tests { 50 | use super::*; 51 | 52 | #[test] 53 | #[should_panic] 54 | fn fail_creating_weightless_package() { 55 | let sender_country = String::from("Spain"); 56 | let recipient_country = String::from("Austria"); 57 | 58 | Package::new(sender_country, recipient_country, 5); 59 | } 60 | 61 | #[test] 62 | fn create_international_package() { 63 | let sender_country = String::from("Spain"); 64 | let recipient_country = String::from("Russia"); 65 | 66 | let package = Package::new(sender_country, recipient_country, 1200); 67 | 68 | assert!(package.is_international()); 69 | } 70 | 71 | #[test] 72 | fn create_local_package() { 73 | let sender_country = String::from("Canada"); 74 | let recipient_country = sender_country.clone(); 75 | 76 | let package = Package::new(sender_country, recipient_country, 1200); 77 | 78 | assert!(!package.is_international()); 79 | } 80 | 81 | #[test] 82 | fn calculate_transport_fees() { 83 | let sender_country = String::from("Spain"); 84 | let recipient_country = String::from("Spain"); 85 | 86 | let cents_per_gram = 3; 87 | 88 | let package = Package::new(sender_country, recipient_country, 1500); 89 | 90 | assert_eq!(package.get_fees(cents_per_gram), 4500); 91 | assert_eq!(package.get_fees(cents_per_gram * 2), 9000); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Rustlings/08_enums/README.md: -------------------------------------------------------------------------------- 1 | # Enums 2 | 3 | Rust allows you to define types called "enums" which enumerate possible values. 4 | Enums are a feature in many languages, but their capabilities differ in each language. Rust’s enums are most similar to algebraic data types in functional languages, such as F#, OCaml, and Haskell. 5 | Useful in combination with enums is Rust's "pattern matching" facility, which makes it easy to run different code for different values of an enumeration. 6 | 7 | ## Further information 8 | 9 | - [Enums](https://doc.rust-lang.org/book/ch06-00-enums.html) 10 | - [Pattern syntax](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html) 11 | -------------------------------------------------------------------------------- /Rustlings/08_enums/enums1.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | enum Message { 3 | // TODO: Define a few types of messages as used below. 4 | Resize, 5 | Move, 6 | Echo, 7 | ChangeColor, 8 | Quit, 9 | } 10 | 11 | fn main() { 12 | println!("{:?}", Message::Resize); 13 | println!("{:?}", Message::Move); 14 | println!("{:?}", Message::Echo); 15 | println!("{:?}", Message::ChangeColor); 16 | println!("{:?}", Message::Quit); 17 | } 18 | -------------------------------------------------------------------------------- /Rustlings/08_enums/enums2.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | use std::env::home_dir; 4 | 5 | #[derive(Debug)] 6 | struct Point { 7 | x: u64, 8 | y: u64, 9 | } 10 | 11 | #[derive(Debug)] 12 | enum Message { 13 | // TODO: Define the different variants used below. 14 | Resize{width:i32,height:i32}, 15 | Move(Point), 16 | Echo(String), 17 | ChangeColor(i32,i32,i32), 18 | Quit, 19 | } 20 | 21 | impl Message { 22 | fn call(&self) { 23 | println!("{self:?}"); 24 | } 25 | } 26 | 27 | fn main() { 28 | let messages = [ 29 | Message::Resize { 30 | width: 10, 31 | height: 30, 32 | }, 33 | Message::Move(Point { x: 10, y: 15 }), 34 | Message::Echo(String::from("hello world")), 35 | Message::ChangeColor(200, 255, 255), 36 | Message::Quit, 37 | ]; 38 | 39 | for message in &messages { 40 | message.call(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Rustlings/08_enums/enums3.rs: -------------------------------------------------------------------------------- 1 | struct Point { 2 | x: u64, 3 | y: u64, 4 | } 5 | 6 | enum Message { 7 | // TODO: Implement the message variant types based on their usage below. 8 | Resize { width: u64, height: u64 }, 9 | Move(Point), 10 | Quit, 11 | Echo(String), 12 | ChangeColor(u8, u8, u8), 13 | } 14 | 15 | struct State { 16 | width: u64, 17 | height: u64, 18 | position: Point, 19 | message: String, 20 | // RGB color composed of red, green and blue. 21 | color: (u8, u8, u8), 22 | quit: bool, 23 | } 24 | 25 | impl State { 26 | fn resize(&mut self, width: u64, height: u64) { 27 | self.width = width; 28 | self.height = height; 29 | } 30 | 31 | fn move_position(&mut self, point: Point) { 32 | self.position = point; 33 | } 34 | 35 | fn echo(&mut self, s: String) { 36 | self.message = s; 37 | } 38 | 39 | fn change_color(&mut self, red: u8, green: u8, blue: u8) { 40 | self.color = (red, green, blue); 41 | } 42 | 43 | fn quit(&mut self) { 44 | self.quit = true; 45 | } 46 | 47 | fn process(&mut self, message: Message) { 48 | // TODO: Create a match expression to process the different message 49 | // variants using the methods defined above. 50 | match message { 51 | Message::Echo(a) => self.echo(a), 52 | Message::Move(p) => self.move_position(p), 53 | Message::Quit => self.quit(), 54 | Message::ChangeColor(r, g, b) => self.change_color(r, g, b), 55 | Message::Resize { width, height } => self.resize(width, height), 56 | } 57 | } 58 | } 59 | 60 | fn main() { 61 | // You can optionally experiment here. 62 | } 63 | 64 | #[cfg(test)] 65 | mod tests { 66 | use super::*; 67 | 68 | #[test] 69 | fn test_match_message_call() { 70 | let mut state = State { 71 | width: 0, 72 | height: 0, 73 | position: Point { x: 0, y: 0 }, 74 | message: String::from("hello world"), 75 | color: (0, 0, 0), 76 | quit: false, 77 | }; 78 | 79 | state.process(Message::Resize { 80 | width: 10, 81 | height: 30, 82 | }); 83 | state.process(Message::Move(Point { x: 10, y: 15 })); 84 | state.process(Message::Echo(String::from("Hello world!"))); 85 | state.process(Message::ChangeColor(255, 0, 255)); 86 | state.process(Message::Quit); 87 | 88 | assert_eq!(state.width, 10); 89 | assert_eq!(state.height, 30); 90 | assert_eq!(state.position.x, 10); 91 | assert_eq!(state.position.y, 15); 92 | assert_eq!(state.message, "Hello world!"); 93 | assert_eq!(state.color, (255, 0, 255)); 94 | assert!(state.quit); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Rustlings/09_strings/README.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | Rust has two string types, a string slice (`&str`) and an owned string (`String`). 4 | We're not going to dictate when you should use which one, but we'll show you how 5 | to identify and create them, as well as use them. 6 | 7 | ## Further information 8 | 9 | - [Strings](https://doc.rust-lang.org/book/ch08-02-strings.html) 10 | -------------------------------------------------------------------------------- /Rustlings/09_strings/strings1.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error without changing the function signature. 2 | fn current_favorite_color() -> String { 3 | "blue".to_string() 4 | } 5 | 6 | fn main() { 7 | let answer = current_favorite_color(); 8 | println!("My current favorite color is {answer}"); 9 | } 10 | -------------------------------------------------------------------------------- /Rustlings/09_strings/strings2.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error in the `main` function without changing this function. 2 | fn is_a_color_word(attempt: &str) -> bool { 3 | attempt == "green" || attempt == "blue" || attempt == "red" 4 | } 5 | 6 | fn main() { 7 | let word = String::from("green"); // Don't change this line. 8 | 9 | if is_a_color_word(&word) { 10 | println!("That is a color word I know!"); 11 | } else { 12 | println!("That is not a color word I know."); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Rustlings/09_strings/strings3.rs: -------------------------------------------------------------------------------- 1 | fn trim_me(input: &str) -> &str { 2 | // TODO: Remove whitespace from both ends of a string. 3 | input.trim() 4 | } 5 | 6 | fn compose_me(input: &str) -> String { 7 | // TODO: Add " world!" to the string! There are multiple ways to do this. 8 | format!("{input} world!") 9 | } 10 | 11 | fn replace_me(input: &str) -> String { 12 | // TODO: Replace "cars" in the string with "balloons". 13 | input.replace("cars", "balloons") 14 | } 15 | 16 | fn main() { 17 | // You can optionally experiment here. 18 | } 19 | 20 | #[cfg(test)] 21 | mod tests { 22 | use super::*; 23 | 24 | #[test] 25 | fn trim_a_string() { 26 | assert_eq!(trim_me("Hello! "), "Hello!"); 27 | assert_eq!(trim_me(" What's up!"), "What's up!"); 28 | assert_eq!(trim_me(" Hola! "), "Hola!"); 29 | } 30 | 31 | #[test] 32 | fn compose_a_string() { 33 | assert_eq!(compose_me("Hello"), "Hello world!"); 34 | assert_eq!(compose_me("Goodbye"), "Goodbye world!"); 35 | } 36 | 37 | #[test] 38 | fn replace_a_string() { 39 | assert_eq!( 40 | replace_me("I think cars are cool"), 41 | "I think balloons are cool", 42 | ); 43 | assert_eq!( 44 | replace_me("I love to look at cars"), 45 | "I love to look at balloons", 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Rustlings/09_strings/strings4.rs: -------------------------------------------------------------------------------- 1 | // Calls of this function should be replaced with calls of `string_slice` or `string`. 2 | fn placeholder() {} 3 | 4 | fn string_slice(arg: &str) { 5 | println!("{arg}"); 6 | } 7 | 8 | fn string(arg: String) { 9 | println!("{arg}"); 10 | } 11 | 12 | // TODO: Here are a bunch of values - some are `String`, some are `&str`. 13 | // Your task is to replace `placeholder(…)` with either `string_slice(…)` 14 | // or `string(…)` depending on what you think each value is. 15 | fn main() { 16 | string_slice("blue"); 17 | 18 | string("red".to_string()); 19 | 20 | string(String::from("hi")); 21 | 22 | string("rust is fun!".to_owned()); 23 | 24 | string("nice weather".into()); 25 | 26 | string(format!("Interpolation {}", "Station")); 27 | 28 | // WARNING: This is byte indexing, not character indexing. 29 | // Character indexing can be done using `s.chars().nth(INDEX)`. 30 | string_slice(&String::from("abc")[0..1]); 31 | 32 | string_slice(" hello there ".trim()); 33 | 34 | string("Happy Monday!".replace("Mon", "Tues")); 35 | 36 | string("mY sHiFt KeY iS sTiCkY".to_lowercase()); 37 | } 38 | -------------------------------------------------------------------------------- /Rustlings/10_modules/README.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | In this section we'll give you an introduction to Rust's module system. 4 | 5 | ## Further information 6 | 7 | - [The Module System](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html) 8 | -------------------------------------------------------------------------------- /Rustlings/10_modules/modules1.rs: -------------------------------------------------------------------------------- 1 | // TODO: Fix the compiler error about calling a private function. 2 | pub mod sausage_factory { 3 | // Don't let anybody outside of this module see this! 4 | fn get_secret_recipe() -> String { 5 | String::from("Ginger") 6 | } 7 | 8 | pub fn make_sausage() { 9 | get_secret_recipe(); 10 | println!("sausage!"); 11 | } 12 | } 13 | 14 | fn main() { 15 | sausage_factory::make_sausage(); 16 | } 17 | -------------------------------------------------------------------------------- /Rustlings/10_modules/modules2.rs: -------------------------------------------------------------------------------- 1 | // You can bring module paths into scopes and provide new names for them with 2 | // the `use` and `as` keywords. 3 | 4 | #[allow(dead_code)] 5 | mod delicious_snacks { 6 | // TODO: Add the following two `use` statements after fixing them. 7 | // use self::fruits::PEAR as ???; 8 | // use self::veggies::CUCUMBER as ???; 9 | 10 | pub use self::fruits::PEAR as fruit; 11 | pub use self::veggies::CUCUMBER as veggie; 12 | 13 | mod fruits { 14 | pub const PEAR: &str = "Pear"; 15 | pub const APPLE: &str = "Apple"; 16 | } 17 | 18 | mod veggies { 19 | pub const CUCUMBER: &str = "Cucumber"; 20 | pub const CARROT: &str = "Carrot"; 21 | } 22 | } 23 | 24 | fn main() { 25 | println!( 26 | "favorite snacks: {} and {}", 27 | delicious_snacks::fruit, 28 | delicious_snacks::veggie, 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /Rustlings/10_modules/modules3.rs: -------------------------------------------------------------------------------- 1 | // You can use the `use` keyword to bring module paths from modules from 2 | // anywhere and especially from the standard library into your scope. 3 | 4 | // TODO: Bring `SystemTime` and `UNIX_EPOCH` from the `std::time` module into 5 | // your scope. Bonus style points if you can do it with one line! 6 | // use ???; 7 | use std::time::{SystemTime,UNIX_EPOCH}; 8 | fn main() { 9 | match SystemTime::now().duration_since(UNIX_EPOCH) { 10 | Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), 11 | Err(_) => panic!("SystemTime before UNIX EPOCH!"), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Rustlings/11_hashmaps/README.md: -------------------------------------------------------------------------------- 1 | # Hashmaps 2 | 3 | A *hash map* allows you to associate a value with a particular key. 4 | You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map), 5 | [*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages. 6 | 7 | This is the other data structure that we've been talking about before, when 8 | talking about Vecs. 9 | 10 | ## Further information 11 | 12 | - [Storing Keys with Associated Values in Hash Maps](https://doc.rust-lang.org/book/ch08-03-hash-maps.html) 13 | -------------------------------------------------------------------------------- /Rustlings/11_hashmaps/hashmaps1.rs: -------------------------------------------------------------------------------- 1 | // A basket of fruits in the form of a hash map needs to be defined. The key 2 | // represents the name of the fruit and the value represents how many of that 3 | // particular fruit is in the basket. You have to put at least 3 different 4 | // types of fruits (e.g. apple, banana, mango) in the basket and the total count 5 | // of all the fruits should be at least 5. 6 | 7 | use std::collections::HashMap; 8 | 9 | fn fruit_basket() -> HashMap { 10 | // TODO: Declare the hash map. 11 | // let mut basket = 12 | let mut basket:HashMap = HashMap::new(); 13 | 14 | // Two bananas are already given for you :) 15 | basket.insert(String::from("banana"), 2); 16 | basket.insert(String::from("apple"), 2); 17 | basket.insert(String::from("orange"), 2); 18 | 19 | // TODO: Put more fruits in your basket. 20 | 21 | basket 22 | } 23 | 24 | fn main() { 25 | // You can optionally experiment here. 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn at_least_three_types_of_fruits() { 34 | let basket = fruit_basket(); 35 | assert!(basket.len() >= 3); 36 | } 37 | 38 | #[test] 39 | fn at_least_five_fruits() { 40 | let basket = fruit_basket(); 41 | assert!(basket.values().sum::() >= 5); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Rustlings/11_hashmaps/hashmaps2.rs: -------------------------------------------------------------------------------- 1 | // We're collecting different fruits to bake a delicious fruit cake. For this, 2 | // we have a basket, which we'll represent in the form of a hash map. The key 3 | // represents the name of each fruit we collect and the value represents how 4 | // many of that particular fruit we have collected. Three types of fruits - 5 | // Apple (4), Mango (2) and Lychee (5) are already in the basket hash map. You 6 | // must add fruit to the basket so that there is at least one of each kind and 7 | // more than 11 in total - we have a lot of mouths to feed. You are not allowed 8 | // to insert any more of the fruits that are already in the basket (Apple, 9 | // Mango, and Lychee). 10 | 11 | use std::collections::HashMap; 12 | 13 | #[derive(Hash, PartialEq, Eq, Debug)] 14 | enum Fruit { 15 | Apple, 16 | Banana, 17 | Mango, 18 | Lychee, 19 | Pineapple, 20 | } 21 | 22 | fn fruit_basket(basket: &mut HashMap) { 23 | let fruit_kinds = [ 24 | Fruit::Apple, 25 | Fruit::Banana, 26 | Fruit::Mango, 27 | Fruit::Lychee, 28 | Fruit::Pineapple, 29 | ]; 30 | 31 | for fruit in fruit_kinds { 32 | // TODO: Insert new fruits if they are not already present in the 33 | // basket. Note that you are not allowed to put any type of fruit that's 34 | // already present!\ 35 | basket.entry(fruit).or_insert(1); 36 | } 37 | } 38 | 39 | fn main() { 40 | // You can optionally experiment here. 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use super::*; 46 | 47 | // Don't modify this function! 48 | fn get_fruit_basket() -> HashMap { 49 | let content = [(Fruit::Apple, 4), (Fruit::Mango, 2), (Fruit::Lychee, 5)]; 50 | HashMap::from_iter(content) 51 | } 52 | 53 | #[test] 54 | fn test_given_fruits_are_not_modified() { 55 | let mut basket = get_fruit_basket(); 56 | fruit_basket(&mut basket); 57 | assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4); 58 | assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2); 59 | assert_eq!(*basket.get(&Fruit::Lychee).unwrap(), 5); 60 | } 61 | 62 | #[test] 63 | fn at_least_five_types_of_fruits() { 64 | let mut basket = get_fruit_basket(); 65 | fruit_basket(&mut basket); 66 | let count_fruit_kinds = basket.len(); 67 | assert!(count_fruit_kinds >= 5); 68 | } 69 | 70 | #[test] 71 | fn greater_than_eleven_fruits() { 72 | let mut basket = get_fruit_basket(); 73 | fruit_basket(&mut basket); 74 | let count = basket.values().sum::(); 75 | assert!(count > 11); 76 | } 77 | 78 | #[test] 79 | fn all_fruit_types_in_basket() { 80 | let fruit_kinds = [ 81 | Fruit::Apple, 82 | Fruit::Banana, 83 | Fruit::Mango, 84 | Fruit::Lychee, 85 | Fruit::Pineapple, 86 | ]; 87 | 88 | let mut basket = get_fruit_basket(); 89 | fruit_basket(&mut basket); 90 | 91 | for fruit_kind in fruit_kinds { 92 | let Some(amount) = basket.get(&fruit_kind) else { 93 | panic!("Fruit kind {fruit_kind:?} was not found in basket"); 94 | }; 95 | assert!(*amount > 0); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Rustlings/11_hashmaps/hashmaps3.rs: -------------------------------------------------------------------------------- 1 | // A list of scores (one per line) of a soccer match is given. Each line is of 2 | // the form ",,," 3 | // Example: "England,France,4,2" (England scored 4 goals, France 2). 4 | // 5 | // You have to build a scores table containing the name of the team, the total 6 | // number of goals the team scored, and the total number of goals the team 7 | // conceded. 8 | 9 | use std::collections::HashMap; 10 | 11 | // A structure to store the goal details of a team. 12 | #[derive(Default)] 13 | struct TeamScores { 14 | goals_scored: u8, 15 | goals_conceded: u8, 16 | } 17 | 18 | fn build_scores_table(results: &str) -> HashMap<&str, TeamScores> { 19 | // The name of the team is the key and its associated struct is the value. 20 | let mut scores = HashMap::new(); 21 | 22 | for line in results.lines() { 23 | let mut split_iterator = line.split(','); 24 | // NOTE: We use `unwrap` because we didn't deal with error handling yet. 25 | let team_1_name = split_iterator.next().unwrap(); 26 | let team_2_name = split_iterator.next().unwrap(); 27 | let team_1_score: u8 = split_iterator.next().unwrap().parse().unwrap(); 28 | let team_2_score: u8 = split_iterator.next().unwrap().parse().unwrap(); 29 | 30 | // TODO: Populate the scores table with the extracted details. 31 | // Keep in mind that goals scored by team 1 will be the number of goals 32 | // conceded by team 2. Similarly, goals scored by team 2 will be the 33 | // number of goals conceded by team 1. 34 | // Insert the default with zeros if a team doesn't exist yet. 35 | let team_1 = scores 36 | .entry(team_1_name) 37 | .or_insert_with(TeamScores::default); 38 | // Update the values. 39 | team_1.goals_scored += team_1_score; 40 | team_1.goals_conceded += team_2_score; 41 | 42 | // Similarly for the second team. 43 | let team_2 = scores 44 | .entry(team_2_name) 45 | .or_insert_with(TeamScores::default); 46 | team_2.goals_scored += team_2_score; 47 | team_2.goals_conceded += team_1_score; 48 | } 49 | 50 | scores 51 | } 52 | 53 | fn main() { 54 | // You can optionally experiment here. 55 | } 56 | 57 | #[cfg(test)] 58 | mod tests { 59 | use super::*; 60 | 61 | const RESULTS: &str = "England,France,4,2 62 | France,Italy,3,1 63 | Poland,Spain,2,0 64 | Germany,England,2,1 65 | England,Spain,1,0"; 66 | 67 | #[test] 68 | fn build_scores() { 69 | let scores = build_scores_table(RESULTS); 70 | 71 | assert!(["England", "France", "Germany", "Italy", "Poland", "Spain"] 72 | .into_iter() 73 | .all(|team_name| scores.contains_key(team_name))); 74 | } 75 | 76 | #[test] 77 | fn validate_team_score_1() { 78 | let scores = build_scores_table(RESULTS); 79 | let team = scores.get("England").unwrap(); 80 | assert_eq!(team.goals_scored, 6); 81 | assert_eq!(team.goals_conceded, 4); 82 | } 83 | 84 | #[test] 85 | fn validate_team_score_2() { 86 | let scores = build_scores_table(RESULTS); 87 | let team = scores.get("Spain").unwrap(); 88 | assert_eq!(team.goals_scored, 0); 89 | assert_eq!(team.goals_conceded, 3); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Rustlings/12_options/README.md: -------------------------------------------------------------------------------- 1 | # Options 2 | 3 | Type Option represents an optional value: every Option is either Some and contains a value, or None, and does not. 4 | Option types are very common in Rust code, as they have a number of uses: 5 | 6 | - Initial values 7 | - Return values for functions that are not defined over their entire input range (partial functions) 8 | - Return value for otherwise reporting simple errors, where None is returned on error 9 | - Optional struct fields 10 | - Struct fields that can be loaned or "taken" 11 | - Optional function arguments 12 | - Nullable pointers 13 | - Swapping things out of difficult situations 14 | 15 | ## Further Information 16 | 17 | - [Option Enum Format](https://doc.rust-lang.org/book/ch10-01-syntax.html#in-enum-definitions) 18 | - [Option Module Documentation](https://doc.rust-lang.org/std/option/) 19 | - [Option Enum Documentation](https://doc.rust-lang.org/std/option/enum.Option.html) 20 | - [if let](https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html) 21 | - [while let](https://doc.rust-lang.org/rust-by-example/flow_control/while_let.html) 22 | -------------------------------------------------------------------------------- /Rustlings/12_options/options1.rs: -------------------------------------------------------------------------------- 1 | // This function returns how much icecream there is left in the fridge. 2 | // If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00, 3 | // someone eats it all, so no icecream is left (value 0). Return `None` if 4 | // `hour_of_day` is higher than 23. 5 | fn maybe_icecream(hour_of_day: u16) -> Option { 6 | // TODO: Complete the function body. 7 | if hour_of_day>=24{ 8 | None 9 | } 10 | else if (22..=23).contains(&hour_of_day) { 11 | Some(0) 12 | } 13 | else{ 14 | Some(5) 15 | } 16 | 17 | } 18 | 19 | fn main() { 20 | // You can optionally experiment here. 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn raw_value() { 29 | // TODO: Fix this test. How do you get the value contained in the 30 | // Option? 31 | let icecreams = maybe_icecream(12).unwrap(); 32 | 33 | assert_eq!(icecreams, 5); // Don't change this line. 34 | } 35 | 36 | #[test] 37 | fn check_icecream() { 38 | assert_eq!(maybe_icecream(0), Some(5)); 39 | assert_eq!(maybe_icecream(9), Some(5)); 40 | assert_eq!(maybe_icecream(18), Some(5)); 41 | assert_eq!(maybe_icecream(22), Some(0)); 42 | assert_eq!(maybe_icecream(23), Some(0)); 43 | assert_eq!(maybe_icecream(24), None); 44 | assert_eq!(maybe_icecream(25), None); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Rustlings/12_options/options2.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // You can optionally experiment here. 3 | } 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | #[test] 8 | fn simple_option() { 9 | let target = "rustlings"; 10 | let optional_target = Some(target); 11 | 12 | // TODO: Make this an if-let statement whose value is `Some`. 13 | if let Some(word) = optional_target { 14 | assert_eq!(word, target); 15 | } 16 | } 17 | 18 | #[test] 19 | fn layered_option() { 20 | let range = 10; 21 | let mut optional_integers: Vec> = vec![None]; 22 | 23 | for i in 1..=range { 24 | optional_integers.push(Some(i)); 25 | } 26 | 27 | let mut cursor = range; 28 | 29 | // TODO: Make this a while-let statement. Remember that `Vec::pop()` 30 | // adds another layer of `Option`. You can do nested pattern matching 31 | // in if-let and while-let statements. 32 | while let Some(Some(integer)) = optional_integers.pop() { 33 | assert_eq!(integer, cursor); 34 | cursor -= 1; 35 | } 36 | 37 | assert_eq!(cursor, 0); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Rustlings/12_options/options3.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | struct Point { 3 | x: i32, 4 | y: i32, 5 | } 6 | 7 | fn main() { 8 | let optional_point = Some(Point { x: 100, y: 200 }); 9 | 10 | // TODO: Fix the compiler error by adding something to this match statement. 11 | match optional_point { 12 | Some(ref p) => println!("Co-ordinates are {},{}", p.x, p.y), 13 | _ => panic!("No match!"), 14 | } 15 | 16 | println!("{optional_point:?}"); // Don't change this line. 17 | } 18 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/README.md: -------------------------------------------------------------------------------- 1 | # Error handling 2 | 3 | Most errors aren’t serious enough to require the program to stop entirely. 4 | Sometimes, when a function fails, it’s for a reason that you can easily interpret and respond to. 5 | For example, if you try to open a file and that operation fails because the file doesn’t exist, you might want to create the file instead of terminating the process. 6 | 7 | ## Further information 8 | 9 | - [Error Handling](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html) 10 | - [Generics](https://doc.rust-lang.org/book/ch10-01-syntax.html) 11 | - [Result](https://doc.rust-lang.org/rust-by-example/error/result.html) 12 | - [Boxing errors](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/boxing_errors.html) 13 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/errors1.rs: -------------------------------------------------------------------------------- 1 | // TODO: This function refuses to generate text to be printed on a nametag if 2 | // you pass it an empty string. It'd be nicer if it explained what the problem 3 | // was instead of just returning `None`. Thankfully, Rust has a similar 4 | // construct to `Option` that can be used to express error conditions. Change 5 | // the function signature and body to return `Result` instead 6 | // of `Option`. 7 | fn generate_nametag_text(name: String) -> Result { 8 | if name.is_empty() { 9 | // Empty names aren't allowed 10 | Err(format!("Empty names aren't allowed")) 11 | } else { 12 | Ok(format!("Hi! My name is {name}")) 13 | } 14 | } 15 | 16 | fn main() { 17 | // You can optionally experiment here. 18 | } 19 | 20 | #[cfg(test)] 21 | mod tests { 22 | use super::*; 23 | 24 | #[test] 25 | fn generates_nametag_text_for_a_nonempty_name() { 26 | assert_eq!( 27 | generate_nametag_text("Beyoncé".to_string()).as_deref(), 28 | Ok("Hi! My name is Beyoncé"), 29 | ); 30 | } 31 | 32 | #[test] 33 | fn explains_why_generating_nametag_text_fails() { 34 | assert_eq!( 35 | generate_nametag_text(String::new()) 36 | .as_ref() 37 | .map_err(|e| e.as_str()), 38 | Err("Empty names aren't allowed"), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/errors2.rs: -------------------------------------------------------------------------------- 1 | // Say we're writing a game where you can buy items with tokens. All items cost 2 | // 5 tokens, and whenever you purchase items there is a processing fee of 1 3 | // token. A player of the game will type in how many items they want to buy, and 4 | // the `total_cost` function will calculate the total cost of the items. Since 5 | // the player typed in the quantity, we get it as a string. They might have 6 | // typed anything, not just numbers! 7 | // 8 | // Right now, this function isn't handling the error case at all. What we want 9 | // to do is: If we call the `total_cost` function on a string that is not a 10 | // number, that function will return a `ParseIntError`. In that case, we want to 11 | // immediately return that error from our function and not try to multiply and 12 | // add. 13 | // 14 | // There are at least two ways to implement this that are both correct. But one 15 | // is a lot shorter! 16 | 17 | use std::num::ParseIntError; 18 | 19 | fn total_cost(item_quantity: &str) -> Result { 20 | let processing_fee = 1; 21 | let cost_per_item = 5; 22 | 23 | // TODO: Handle the error case as described above. 24 | let qty = item_quantity.parse::()?; 25 | 26 | Ok(qty * cost_per_item + processing_fee) 27 | } 28 | 29 | fn main() { 30 | // You can optionally experiment here. 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | use std::num::IntErrorKind; 37 | 38 | #[test] 39 | fn item_quantity_is_a_valid_number() { 40 | assert_eq!(total_cost("34"), Ok(171)); 41 | } 42 | 43 | #[test] 44 | fn item_quantity_is_an_invalid_number() { 45 | assert_eq!( 46 | total_cost("beep boop").unwrap_err().kind(), 47 | &IntErrorKind::InvalidDigit, 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/errors3.rs: -------------------------------------------------------------------------------- 1 | // This is a program that is trying to use a completed version of the 2 | // `total_cost` function from the previous exercise. It's not working though! 3 | // Why not? What should we do to fix it? 4 | 5 | use std::num::ParseIntError; 6 | 7 | // Don't change this function. 8 | fn total_cost(item_quantity: &str) -> Result { 9 | let processing_fee = 1; 10 | let cost_per_item = 5; 11 | let qty = item_quantity.parse::()?; 12 | 13 | Ok(qty * cost_per_item + processing_fee) 14 | } 15 | 16 | // TODO: Fix the compiler error by changing the signature and body of the 17 | // `main` function. 18 | fn main() -> Result<(),Box>{ 19 | let mut tokens = 100; 20 | let pretend_user_input = "8"; 21 | 22 | // Don't change this line. 23 | let cost = total_cost(pretend_user_input)?; 24 | 25 | if cost > tokens { 26 | println!("You can't afford that many!"); 27 | } else { 28 | tokens -= cost; 29 | println!("You now have {tokens} tokens."); 30 | } 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/errors4.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | #[derive(PartialEq, Debug)] 3 | enum CreationError { 4 | Negative, 5 | Zero, 6 | } 7 | 8 | #[derive(PartialEq, Debug)] 9 | struct PositiveNonzeroInteger(u64); 10 | 11 | impl PositiveNonzeroInteger { 12 | fn new(value: i64) -> Result { 13 | match value.cmp(&0) { 14 | Ordering::Less => Err(CreationError::Negative), 15 | Ordering::Equal => Err(CreationError::Zero), 16 | Ordering::Greater => Ok(Self(value as u64)), 17 | } 18 | } 19 | } 20 | 21 | fn main() { 22 | // You can optionally experiment here. 23 | } 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | 29 | #[test] 30 | fn test_creation() { 31 | assert_eq!( 32 | PositiveNonzeroInteger::new(10), 33 | Ok(PositiveNonzeroInteger(10)), 34 | ); 35 | assert_eq!( 36 | PositiveNonzeroInteger::new(-10), 37 | Err(CreationError::Negative), 38 | ); 39 | assert_eq!(PositiveNonzeroInteger::new(0), Err(CreationError::Zero)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/errors5.rs: -------------------------------------------------------------------------------- 1 | // This exercise is an altered version of the `errors4` exercise. It uses some 2 | // concepts that we won't get to until later in the course, like `Box` and the 3 | // `From` trait. It's not important to understand them in detail right now, but 4 | // you can read ahead if you like. For now, think of the `Box` type as 5 | // an "I want anything that does ???" type. 6 | // 7 | // In short, this particular use case for boxes is for when you want to own a 8 | // value and you care only that it is a type which implements a particular 9 | // trait. To do so, The `Box` is declared as of type `Box` where 10 | // `Trait` is the trait the compiler looks for on any value used in that 11 | // context. For this exercise, that context is the potential errors which 12 | // can be returned in a `Result`. 13 | 14 | use std::error::Error; 15 | use std::fmt; 16 | 17 | #[derive(PartialEq, Debug)] 18 | enum CreationError { 19 | Negative, 20 | Zero, 21 | } 22 | 23 | // This is required so that `CreationError` can implement `Error`. 24 | impl fmt::Display for CreationError { 25 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 26 | let description = match *self { 27 | CreationError::Negative => "number is negative", 28 | CreationError::Zero => "number is zero", 29 | }; 30 | f.write_str(description) 31 | } 32 | } 33 | 34 | impl Error for CreationError {} 35 | 36 | #[derive(PartialEq, Debug)] 37 | struct PositiveNonzeroInteger(u64); 38 | 39 | impl PositiveNonzeroInteger { 40 | fn new(value: i64) -> Result { 41 | match value { 42 | x if x < 0 => Err(CreationError::Negative), 43 | 0 => Err(CreationError::Zero), 44 | x => Ok(PositiveNonzeroInteger(x as u64)), 45 | } 46 | } 47 | } 48 | 49 | // TODO: Add the correct return type `Result<(), Box>`. What can we 50 | // use to describe both errors? Is there a trait which both errors implement? 51 | fn main()->Result<(), Box>{ 52 | let pretend_user_input = "42"; 53 | let x: i64 = pretend_user_input.parse()?; 54 | println!("output={:?}", PositiveNonzeroInteger::new(x)?); 55 | Ok(()) 56 | } 57 | -------------------------------------------------------------------------------- /Rustlings/13_error_handling/errors6.rs: -------------------------------------------------------------------------------- 1 | 2 | // Using catch-all error types like `Box` isn't recommended for 3 | // library code where callers might want to make decisions based on the error 4 | // content instead of printing it out or propagating it further. Here, we define 5 | // a custom error type to make it possible for callers to decide what to do next 6 | // when our function returns an error. 7 | 8 | use std::num::ParseIntError; 9 | 10 | #[derive(PartialEq, Debug)] 11 | enum CreationError { 12 | Negative, 13 | Zero, 14 | } 15 | 16 | // A custom error type that we will be using in `PositiveNonzeroInteger::parse`. 17 | #[derive(PartialEq, Debug)] 18 | enum ParsePosNonzeroError { 19 | Creation(CreationError), 20 | ParseInt(ParseIntError), 21 | } 22 | 23 | impl ParsePosNonzeroError { 24 | fn from_creation(err: CreationError) -> Self { 25 | Self::Creation(err) 26 | } 27 | 28 | fn from_parse_int(err: ParseIntError) -> Self { 29 | Self::ParseInt(err) 30 | } 31 | } 32 | 33 | #[derive(PartialEq, Debug)] 34 | struct PositiveNonzeroInteger(u64); 35 | 36 | impl PositiveNonzeroInteger { 37 | fn new(value: i64) -> Result { 38 | match value { 39 | x if x < 0 => Err(CreationError::Negative), 40 | 0 => Err(CreationError::Zero), 41 | x => Ok(Self(x as u64)), 42 | } 43 | } 44 | 45 | fn parse(s: &str) -> Result { 46 | // Return an appropriate error instead of panicking when `parse()` 47 | // returns an error. 48 | let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?; 49 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 50 | Self::new(x).map_err(ParsePosNonzeroError::from_creation) 51 | } 52 | } 53 | 54 | fn main() { 55 | // You can optionally experiment here. 56 | } 57 | 58 | #[cfg(test)] 59 | mod test { 60 | use super::*; 61 | 62 | #[test] 63 | fn test_parse_error() { 64 | assert!(matches!( 65 | PositiveNonzeroInteger::parse("not a number"), 66 | Err(ParsePosNonzeroError::ParseInt(_)), 67 | )); 68 | } 69 | 70 | #[test] 71 | fn test_negative() { 72 | assert_eq!( 73 | PositiveNonzeroInteger::parse("-555"), 74 | Err(ParsePosNonzeroError::Creation(CreationError::Negative)), 75 | ); 76 | } 77 | 78 | #[test] 79 | fn test_zero() { 80 | assert_eq!( 81 | PositiveNonzeroInteger::parse("0"), 82 | Err(ParsePosNonzeroError::Creation(CreationError::Zero)), 83 | ); 84 | } 85 | 86 | #[test] 87 | fn test_positive() { 88 | let x = PositiveNonzeroInteger::new(42).unwrap(); 89 | assert_eq!(x.0, 42); 90 | assert_eq!(PositiveNonzeroInteger::parse("42"), Ok(x)); 91 | } 92 | } -------------------------------------------------------------------------------- /Rustlings/14_generics/README.md: -------------------------------------------------------------------------------- 1 | # Generics 2 | 3 | Generics is the topic of generalizing types and functionalities to broader cases. 4 | This is extremely useful for reducing code duplication in many ways, but can call for some rather involved syntax. 5 | Namely, being generic requires taking great care to specify over which types a generic type is actually considered valid. 6 | The simplest and most common use of generics is for type parameters. 7 | 8 | ## Further information 9 | 10 | - [Generic Data Types](https://doc.rust-lang.org/book/ch10-01-syntax.html) 11 | - [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html) 12 | -------------------------------------------------------------------------------- /Rustlings/14_generics/generics1.rs: -------------------------------------------------------------------------------- 1 | // `Vec` is generic over the type `T`. In most cases, the compiler is able to 2 | // infer `T`, for example after pushing a value with a concrete type to the vector. 3 | // But in this exercise, the compiler needs some help through a type annotation. 4 | 5 | fn main() { 6 | // TODO: Fix the compiler error by annotating the type of the vector 7 | // `Vec`. Choose `T` as some integer type that can be created from 8 | // `u8` and `i8`. 9 | let mut numbers:Vec = Vec::new(); 10 | 11 | // Don't change the lines below. 12 | let n1: u8 = 42; 13 | numbers.push(n1.into()); 14 | let n2: i8 = -1; 15 | numbers.push(n2.into()); 16 | 17 | println!("{numbers:?}"); 18 | } 19 | -------------------------------------------------------------------------------- /Rustlings/14_generics/generics2.rs: -------------------------------------------------------------------------------- 1 | // This powerful wrapper provides the ability to store a positive integer value. 2 | // TODO: Rewrite it using a generic so that it supports wrapping ANY type. 3 | struct Wrapper { 4 | value: T, 5 | } 6 | 7 | // TODO: Adapt the struct's implementation to be generic over the wrapped value. 8 | impl Wrapper { 9 | fn new(value: T) -> Self { 10 | Wrapper { value } 11 | } 12 | } 13 | 14 | fn main() { 15 | // You can optionally experiment here. 16 | } 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | use super::*; 21 | 22 | #[test] 23 | fn store_u32_in_wrapper() { 24 | assert_eq!(Wrapper::new(42).value, 42); 25 | } 26 | 27 | #[test] 28 | fn store_str_in_wrapper() { 29 | assert_eq!(Wrapper::new("Foo").value, "Foo"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Rustlings/15_traits/README.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 | A trait is a collection of methods. 4 | 5 | Data types can implement traits. To do so, the methods making up the trait are defined for the data type. For example, the `String` data type implements the `From<&str>` trait. This allows a user to write `String::from("hello")`. 6 | 7 | In this way, traits are somewhat similar to Java interfaces and C++ abstract classes. 8 | 9 | Some additional common Rust traits include: 10 | 11 | - `Clone` (the `clone` method) 12 | - `Display` (which allows formatted display via `{}`) 13 | - `Debug` (which allows formatted display via `{:?}`) 14 | 15 | Because traits indicate shared behavior between data types, they are useful when writing generics. 16 | 17 | ## Further information 18 | 19 | - [Traits](https://doc.rust-lang.org/book/ch10-02-traits.html) 20 | -------------------------------------------------------------------------------- /Rustlings/15_traits/traits1.rs: -------------------------------------------------------------------------------- 1 | // The trait `AppendBar` has only one function which appends "Bar" to any object 2 | // implementing this trait. 3 | trait AppendBar { 4 | fn append_bar(self) -> Self; 5 | } 6 | 7 | impl AppendBar for String { 8 | // TODO: Implement `AppendBar` for the type `String`. 9 | fn append_bar(mut self) -> Self { 10 | self.push_str("Bar"); 11 | self 12 | } 13 | } 14 | 15 | fn main() { 16 | let s = String::from("Foo"); 17 | let s = s.append_bar(); 18 | println!("s: {s}"); 19 | } 20 | 21 | #[cfg(test)] 22 | mod tests { 23 | use super::*; 24 | 25 | #[test] 26 | fn is_foo_bar() { 27 | assert_eq!(String::from("Foo").append_bar(), "FooBar"); 28 | } 29 | 30 | #[test] 31 | fn is_bar_bar() { 32 | assert_eq!(String::from("").append_bar().append_bar(), "BarBar"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Rustlings/15_traits/traits2.rs: -------------------------------------------------------------------------------- 1 | trait AppendBar { 2 | fn append_bar(self) -> Self; 3 | } 4 | 5 | // TODO: Implement the trait `AppendBar` for a vector of strings. 6 | // `append_bar` should push the string "Bar" into the vector. 7 | 8 | impl AppendBar for Vec { 9 | fn append_bar(mut self) -> Self { 10 | self.push("Bar".to_string()); 11 | self 12 | } 13 | } 14 | 15 | fn main() { 16 | // You can optionally experiment here. 17 | } 18 | 19 | #[cfg(test)] 20 | mod tests { 21 | use super::*; 22 | 23 | #[test] 24 | fn is_vec_pop_eq_bar() { 25 | let mut foo = vec![String::from("Foo")].append_bar(); 26 | assert_eq!(foo.pop().unwrap(), "Bar"); 27 | assert_eq!(foo.pop().unwrap(), "Foo"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Rustlings/15_traits/traits3.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | trait Licensed { 4 | // TODO: Add a default implementation for `licensing_info` so that 5 | // implementors like the two structs below can share that default behavior 6 | // without repeating the function. 7 | // The default license information should be the string "Default license". 8 | fn licensing_info(&self) -> String{ 9 | "Default license".to_string() 10 | } 11 | } 12 | 13 | struct SomeSoftware { 14 | version_number: i32, 15 | } 16 | 17 | struct OtherSoftware { 18 | version_number: String, 19 | } 20 | 21 | impl Licensed for SomeSoftware {} // Don't edit this line. 22 | impl Licensed for OtherSoftware {} // Don't edit this line. 23 | 24 | fn main() { 25 | // You can optionally experiment here. 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn is_licensing_info_the_same() { 34 | let licensing_info = "Default license"; 35 | let some_software = SomeSoftware { version_number: 1 }; 36 | let other_software = OtherSoftware { 37 | version_number: "v2.0.0".to_string(), 38 | }; 39 | assert_eq!(some_software.licensing_info(), licensing_info); 40 | assert_eq!(other_software.licensing_info(), licensing_info); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Rustlings/15_traits/traits4.rs: -------------------------------------------------------------------------------- 1 | trait Licensed { 2 | fn licensing_info(&self) -> String { 3 | "Default license".to_string() 4 | } 5 | } 6 | 7 | struct SomeSoftware; 8 | struct OtherSoftware; 9 | 10 | impl Licensed for SomeSoftware {} 11 | impl Licensed for OtherSoftware {} 12 | 13 | // TODO: Fix the compiler error by only changing the signature of this function. 14 | fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool { 15 | software1.licensing_info() == software2.licensing_info() 16 | } 17 | 18 | fn main() { 19 | // You can optionally experiment here. 20 | } 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::*; 25 | 26 | #[test] 27 | fn compare_license_information() { 28 | assert!(compare_license_types(SomeSoftware, OtherSoftware)); 29 | } 30 | 31 | #[test] 32 | fn compare_license_information_backwards() { 33 | assert!(compare_license_types(OtherSoftware, SomeSoftware)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Rustlings/15_traits/traits5.rs: -------------------------------------------------------------------------------- 1 | trait SomeTrait { 2 | fn some_function(&self) -> bool { 3 | true 4 | } 5 | } 6 | 7 | trait OtherTrait { 8 | fn other_function(&self) -> bool { 9 | true 10 | } 11 | } 12 | 13 | struct SomeStruct; 14 | impl SomeTrait for SomeStruct {} 15 | impl OtherTrait for SomeStruct {} 16 | 17 | struct OtherStruct; 18 | impl SomeTrait for OtherStruct {} 19 | impl OtherTrait for OtherStruct {} 20 | 21 | // TODO: Fix the compiler error by only changing the signature of this function. 22 | fn some_func(item: T) -> bool { 23 | item.some_function() && item.other_function() 24 | } 25 | 26 | fn main() { 27 | // You can optionally experiment here. 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use super::*; 33 | 34 | #[test] 35 | fn test_some_func() { 36 | assert!(some_func(SomeStruct)); 37 | assert!(some_func(OtherStruct)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Rustlings/16_lifetimes/README.md: -------------------------------------------------------------------------------- 1 | # Lifetimes 2 | 3 | Lifetimes tell the compiler how to check whether references live long 4 | enough to be valid in any given situation. For example lifetimes say 5 | "make sure parameter 'a' lives as long as parameter 'b' so that the return 6 | value is valid". 7 | 8 | They are only necessary on borrows, i.e. references, 9 | since copied parameters or moves are owned in their scope and cannot 10 | be referenced outside. Lifetimes mean that calling code of e.g. functions 11 | can be checked to make sure their arguments are valid. Lifetimes are 12 | restrictive of their callers. 13 | 14 | If you'd like to learn more about lifetime annotations, the 15 | [lifetimekata](https://tfpk.github.io/lifetimekata/) project 16 | has a similar style of exercises to Rustlings, but is all about 17 | learning to write lifetime annotations. 18 | 19 | ## Further information 20 | 21 | - [Lifetimes (in Rust By Example)](https://doc.rust-lang.org/stable/rust-by-example/scope/lifetime.html) 22 | - [Validating References with Lifetimes](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html) 23 | -------------------------------------------------------------------------------- /Rustlings/16_lifetimes/lifetimes1.rs: -------------------------------------------------------------------------------- 1 | // The Rust compiler needs to know how to check whether supplied references are 2 | // valid, so that it can let the programmer know if a reference is at risk of 3 | // going out of scope before it is used. Remember, references are borrows and do 4 | // not own their own data. What if their owner goes out of scope? 5 | 6 | // TODO: Fix the compiler error by updating the function signature. 7 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 8 | if x.len() > y.len() { 9 | x 10 | } else { 11 | y 12 | } 13 | } 14 | 15 | fn main() { 16 | // You can optionally experiment here. 17 | } 18 | 19 | #[cfg(test)] 20 | mod tests { 21 | use super::*; 22 | 23 | #[test] 24 | fn test_longest() { 25 | assert_eq!(longest("abcd", "123"), "abcd"); 26 | assert_eq!(longest("abc", "1234"), "1234"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Rustlings/16_lifetimes/lifetimes2.rs: -------------------------------------------------------------------------------- 1 | // Don't change this function. 2 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 3 | if x.len() > y.len() { 4 | x 5 | } else { 6 | y 7 | } 8 | } 9 | 10 | fn main() { 11 | // TODO: Fix the compiler error by moving one line. 12 | 13 | let string1 = String::from("long string is long"); 14 | let string2 = String::from("xyz"); 15 | let result; 16 | { 17 | result = longest(&string1, &string2); 18 | } 19 | println!("The longest string is '{result}'"); 20 | } 21 | -------------------------------------------------------------------------------- /Rustlings/16_lifetimes/lifetimes3.rs: -------------------------------------------------------------------------------- 1 | // Lifetimes are also needed when structs hold references. 2 | 3 | // TODO: Fix the compiler errors about the struct. 4 | struct Book <'a>{ 5 | author: &'a str, 6 | title: &'a str, 7 | } 8 | 9 | fn main() { 10 | let book = Book { 11 | author: "George Orwell", 12 | title: "1984", 13 | }; 14 | 15 | println!("{} by {}", book.title, book.author); 16 | } 17 | -------------------------------------------------------------------------------- /Rustlings/17_tests/README.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | Going out of order from the book to cover tests -- many of the following exercises will ask you to make tests pass! 4 | 5 | ## Further information 6 | 7 | - [Writing Tests](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) 8 | -------------------------------------------------------------------------------- /Rustlings/17_tests/tests1.rs: -------------------------------------------------------------------------------- 1 | // Tests are important to ensure that your code does what you think it should 2 | // do. 3 | 4 | fn is_even(n: i64) -> bool { 5 | n % 2 == 0 6 | } 7 | 8 | fn main() { 9 | // You can optionally experiment here. 10 | } 11 | 12 | #[cfg(test)] 13 | mod tests { 14 | // TODO: Import `is_even`. You can use a wildcard to import everything in 15 | // the outer module. 16 | use super::*; 17 | 18 | #[test] 19 | fn you_can_assert() { 20 | // TODO: Test the function `is_even` with some values. 21 | assert!(is_even(2)); 22 | assert!(!is_even(1)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Rustlings/17_tests/tests2.rs: -------------------------------------------------------------------------------- 1 | // Calculates the power of 2 using a bit shift. 2 | // `1 << n` is equivalent to "2 to the power of n". 3 | fn power_of_2(n: u8) -> u64 { 4 | 1 << n 5 | } 6 | 7 | fn main() { 8 | // You can optionally experiment here. 9 | } 10 | 11 | #[cfg(test)] 12 | mod tests { 13 | use super::*; 14 | 15 | #[test] 16 | fn you_can_assert_eq() { 17 | // TODO: Test the function `power_of_2` with some values. 18 | assert_eq!(2,power_of_2(1)); 19 | assert_eq!(4,power_of_2(2)); 20 | assert_eq!(8,power_of_2(3)); 21 | assert_eq!(16,power_of_2(4)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Rustlings/17_tests/tests3.rs: -------------------------------------------------------------------------------- 1 | struct Rectangle { 2 | width: i32, 3 | height: i32, 4 | } 5 | 6 | impl Rectangle { 7 | // Don't change this function. 8 | fn new(width: i32, height: i32) -> Self { 9 | if width <= 0 || height <= 0 { 10 | // Returning a `Result` would be better here. But we want to learn 11 | // how to test functions that can panic. 12 | panic!("Rectangle width and height must be positive"); 13 | } 14 | 15 | Rectangle { width, height } 16 | } 17 | } 18 | 19 | fn main() { 20 | // You can optionally experiment here. 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn correct_width_and_height() { 29 | let rect = Rectangle::new(10, 20); 30 | assert_eq!(rect.width, 10); // Check width 31 | assert_eq!(rect.height, 20); // Check height 32 | } 33 | 34 | #[test] 35 | #[should_panic] // Added this attribute to check that the test panics. 36 | fn negative_width() { 37 | let _rect = Rectangle::new(-10, 10); 38 | } 39 | 40 | #[test] 41 | #[should_panic] // Added this attribute to check that the test panics. 42 | fn negative_height() { 43 | let _rect = Rectangle::new(10, -10); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Rustlings/18_iterators/README.md: -------------------------------------------------------------------------------- 1 | # Iterators 2 | 3 | This section will teach you about Iterators. 4 | 5 | ## Further information 6 | 7 | - [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html) 8 | - [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/) 9 | -------------------------------------------------------------------------------- /Rustlings/18_iterators/iterators1.rs: -------------------------------------------------------------------------------- 1 | // When performing operations on elements within a collection, iterators are 2 | // essential. This module helps you get familiar with the structure of using an 3 | // iterator and how to go through elements within an iterable collection. 4 | 5 | fn main() { 6 | // You can optionally experiment here. 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | #[test] 12 | fn iterators() { 13 | let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"]; 14 | 15 | // TODO: Create an iterator over the array. 16 | let mut fav_fruits_iterator = my_fav_fruits.iter(); 17 | 18 | assert_eq!(fav_fruits_iterator.next(), Some(&"banana")); 19 | assert_eq!(fav_fruits_iterator.next(), Some(&"custard apple")); // TODO: Replace `todo!()` 20 | assert_eq!(fav_fruits_iterator.next(), Some(&"avocado")); 21 | assert_eq!(fav_fruits_iterator.next(), Some(&"peach")); // TODO: Replace `todo!()` 22 | assert_eq!(fav_fruits_iterator.next(), Some(&"raspberry")); 23 | assert_eq!(fav_fruits_iterator.next(), None); // TODO: Replace `todo!()` 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Rustlings/18_iterators/iterators2.rs: -------------------------------------------------------------------------------- 1 | // In this exercise, you'll learn some of the unique advantages that iterators 2 | // can offer. 3 | 4 | 5 | // TODO: Complete the `capitalize_first` function. 6 | // "hello" -> "Hello" 7 | fn capitalize_first(input: &str) -> String { 8 | let mut chars = input.chars(); 9 | match chars.next() { 10 | None => String::new(), 11 | Some(first) => first.to_uppercase().to_string()+chars.as_str(), 12 | } 13 | } 14 | 15 | // TODO: Apply the `capitalize_first` function to a slice of string slices. 16 | // Return a vector of strings. 17 | // ["hello", "world"] -> ["Hello", "World"] 18 | fn capitalize_words_vector(words: &[&str]) -> Vec { 19 | words.iter().map(|word| capitalize_first(word)).collect() 20 | } 21 | 22 | // TODO: Apply the `capitalize_first` function again to a slice of string 23 | // slices. Return a single string. 24 | // ["hello", " ", "world"] -> "Hello World" 25 | fn capitalize_words_string(words: &[&str]) -> String { 26 | words.iter().map(|word| capitalize_first(word)).collect() 27 | } 28 | 29 | fn main() { 30 | // You can optionally experiment here. 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | 37 | #[test] 38 | fn test_success() { 39 | assert_eq!(capitalize_first("hello"), "Hello"); 40 | } 41 | 42 | #[test] 43 | fn test_empty() { 44 | assert_eq!(capitalize_first(""), ""); 45 | } 46 | 47 | #[test] 48 | fn test_iterate_string_vec() { 49 | let words = vec!["hello", "world"]; 50 | assert_eq!(capitalize_words_vector(&words), ["Hello", "World"]); 51 | } 52 | 53 | #[test] 54 | fn test_iterate_into_string() { 55 | let words = vec!["hello", " ", "world"]; 56 | assert_eq!(capitalize_words_string(&words), "Hello World"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Rustlings/18_iterators/iterators3.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | enum DivisionError { 3 | // Example: 42 / 0 4 | DivideByZero, 5 | // Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1` 6 | IntegerOverflow, 7 | // Example: 5 / 2 = 2.5 8 | NotDivisible, 9 | } 10 | 11 | // TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`. 12 | // Otherwise, return a suitable error. 13 | fn divide(a: i64, b: i64) -> Result { 14 | if b == 0 { 15 | return Err(DivisionError::DivideByZero); 16 | } 17 | 18 | if a == i64::MIN && b == -1 { 19 | return Err(DivisionError::IntegerOverflow); 20 | } 21 | 22 | if a % b != 0 { 23 | return Err(DivisionError::NotDivisible); 24 | } 25 | 26 | Ok(a / b) 27 | } 28 | 29 | // TODO: Add the correct return type and complete the function body. 30 | // Desired output: `Ok([1, 11, 1426, 3])` 31 | fn result_with_list()-> Result, DivisionError> { 32 | let numbers = [27, 297, 38502, 81]; 33 | let division_results = numbers.into_iter().map(|n| divide(n, 27)); 34 | division_results.collect() 35 | } 36 | 37 | // TODO: Add the correct return type and complete the function body. 38 | // Desired output: `[Ok(1), Ok(11), Ok(1426), Ok(3)]` 39 | fn list_of_results() -> Vec> { 40 | let numbers = [27, 297, 38502, 81]; 41 | let division_results = numbers.into_iter().map(|n| divide(n, 27)); 42 | division_results.collect() 43 | 44 | } 45 | 46 | fn main() { 47 | // You can optionally experiment here. 48 | } 49 | 50 | #[cfg(test)] 51 | mod tests { 52 | use super::*; 53 | 54 | #[test] 55 | fn test_success() { 56 | assert_eq!(divide(81, 9), Ok(9)); 57 | } 58 | 59 | #[test] 60 | fn test_divide_by_0() { 61 | assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero)); 62 | } 63 | 64 | #[test] 65 | fn test_integer_overflow() { 66 | assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow)); 67 | } 68 | 69 | #[test] 70 | fn test_not_divisible() { 71 | assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible)); 72 | } 73 | 74 | #[test] 75 | fn test_divide_0_by_something() { 76 | assert_eq!(divide(0, 81), Ok(0)); 77 | } 78 | 79 | #[test] 80 | fn test_result_with_list() { 81 | assert_eq!(result_with_list().unwrap(), [1, 11, 1426, 3]); 82 | } 83 | 84 | #[test] 85 | fn test_list_of_results() { 86 | assert_eq!(list_of_results(), [Ok(1), Ok(11), Ok(1426), Ok(3)]); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Rustlings/18_iterators/iterators4.rs: -------------------------------------------------------------------------------- 1 | //fn factorial(num: u64) -> u64 { 2 | // TODO: Complete this function to return the factorial of `num` which is 3 | // defined as `1 * 2 * 3 * … * num`. 4 | // https://en.wikipedia.org/wiki/Factorial 5 | // 6 | // Do not use: 7 | // - early returns (using the `return` keyword explicitly) 8 | // Try not to use: 9 | // - imperative style loops (for/while) 10 | // - additional variables 11 | // For an extra challenge, don't use: 12 | // - recursion 13 | //} 14 | fn factorial(num: u64) -> u64 { 15 | let mut result = 1; 16 | 17 | for x in 2..=num { 18 | result *= x; 19 | } 20 | 21 | result 22 | } 23 | fn main() { 24 | // You can optionally experiment here. 25 | } 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | 31 | #[test] 32 | fn factorial_of_0() { 33 | assert_eq!(factorial(0), 1); 34 | } 35 | 36 | #[test] 37 | fn factorial_of_1() { 38 | assert_eq!(factorial(1), 1); 39 | } 40 | #[test] 41 | fn factorial_of_2() { 42 | assert_eq!(factorial(2), 2); 43 | } 44 | 45 | #[test] 46 | fn factorial_of_4() { 47 | assert_eq!(factorial(4), 24); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Rustlings/18_iterators/iterators5.rs: -------------------------------------------------------------------------------- 1 | // Let's define a simple model to track Rustlings' exercise progress. Progress 2 | // will be modelled using a hash map. The name of the exercise is the key and 3 | // the progress is the value. Two counting functions were created to count the 4 | // number of exercises with a given progress. Recreate this counting 5 | // functionality using iterators. Try to not use imperative loops (for/while). 6 | 7 | use std::collections::HashMap; 8 | 9 | #[derive(Clone, Copy, PartialEq, Eq)] 10 | enum Progress { 11 | None, 12 | Some, 13 | Complete, 14 | } 15 | 16 | fn count_for(map: &HashMap, value: Progress) -> usize { 17 | let mut count = 0; 18 | for val in map.values() { 19 | if *val == value { 20 | count += 1; 21 | } 22 | } 23 | count 24 | } 25 | 26 | // TODO: Implement the functionality of `count_for` but with an iterator instead 27 | // of a `for` loop. 28 | fn count_iterator(map: &HashMap, value: Progress) -> usize { 29 | // `map` is a hash map with `String` keys and `Progress` values. 30 | // map = { "variables1": Complete, "from_str": None, … } 31 | map.values().filter(|val| **val == value).count() 32 | } 33 | 34 | fn count_collection_for(collection: &[HashMap], value: Progress) -> usize { 35 | let mut count = 0; 36 | for map in collection { 37 | for val in map.values() { 38 | if *val == value { 39 | count += 1; 40 | } 41 | } 42 | } 43 | count 44 | } 45 | 46 | // TODO: Implement the functionality of `count_collection_for` but with an 47 | // iterator instead of a `for` loop. 48 | fn count_collection_iterator(collection: &[HashMap], value: Progress) -> usize { 49 | // `collection` is a slice of hash maps. 50 | // collection = [{ "variables1": Complete, "from_str": None, … }, 51 | // { "variables2": Complete, … }, … ] 52 | collection 53 | .iter() 54 | .map(|map| count_iterator(map, value)) 55 | .sum() 56 | } 57 | 58 | fn main() { 59 | // You can optionally experiment here. 60 | } 61 | 62 | #[cfg(test)] 63 | mod tests { 64 | use super::*; 65 | 66 | fn get_map() -> HashMap { 67 | use Progress::*; 68 | 69 | let mut map = HashMap::new(); 70 | map.insert(String::from("variables1"), Complete); 71 | map.insert(String::from("functions1"), Complete); 72 | map.insert(String::from("hashmap1"), Complete); 73 | map.insert(String::from("arc1"), Some); 74 | map.insert(String::from("as_ref_mut"), None); 75 | map.insert(String::from("from_str"), None); 76 | 77 | map 78 | } 79 | 80 | fn get_vec_map() -> Vec> { 81 | use Progress::*; 82 | 83 | let map = get_map(); 84 | 85 | let mut other = HashMap::new(); 86 | other.insert(String::from("variables2"), Complete); 87 | other.insert(String::from("functions2"), Complete); 88 | other.insert(String::from("if1"), Complete); 89 | other.insert(String::from("from_into"), None); 90 | other.insert(String::from("try_from_into"), None); 91 | 92 | vec![map, other] 93 | } 94 | 95 | #[test] 96 | fn count_complete() { 97 | let map = get_map(); 98 | assert_eq!(count_iterator(&map, Progress::Complete), 3); 99 | } 100 | 101 | #[test] 102 | fn count_some() { 103 | let map = get_map(); 104 | assert_eq!(count_iterator(&map, Progress::Some), 1); 105 | } 106 | 107 | #[test] 108 | fn count_none() { 109 | let map = get_map(); 110 | assert_eq!(count_iterator(&map, Progress::None), 2); 111 | } 112 | 113 | #[test] 114 | fn count_complete_equals_for() { 115 | let map = get_map(); 116 | let progress_states = [Progress::Complete, Progress::Some, Progress::None]; 117 | for progress_state in progress_states { 118 | assert_eq!( 119 | count_for(&map, progress_state), 120 | count_iterator(&map, progress_state), 121 | ); 122 | } 123 | } 124 | 125 | #[test] 126 | fn count_collection_complete() { 127 | let collection = get_vec_map(); 128 | assert_eq!( 129 | count_collection_iterator(&collection, Progress::Complete), 130 | 6, 131 | ); 132 | } 133 | 134 | #[test] 135 | fn count_collection_some() { 136 | let collection = get_vec_map(); 137 | assert_eq!(count_collection_iterator(&collection, Progress::Some), 1); 138 | } 139 | 140 | #[test] 141 | fn count_collection_none() { 142 | let collection = get_vec_map(); 143 | assert_eq!(count_collection_iterator(&collection, Progress::None), 4); 144 | } 145 | 146 | #[test] 147 | fn count_collection_equals_for() { 148 | let collection = get_vec_map(); 149 | let progress_states = [Progress::Complete, Progress::Some, Progress::None]; 150 | 151 | for progress_state in progress_states { 152 | assert_eq!( 153 | count_collection_for(&collection, progress_state), 154 | count_collection_iterator(&collection, progress_state), 155 | ); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /Rustlings/quizzes/README.md: -------------------------------------------------------------------------------- 1 | # Quizzes 2 | 3 | After every couple of sections, there will be a quiz in this directory that'll test your knowledge on a bunch of sections at once. 4 | -------------------------------------------------------------------------------- /Rustlings/quizzes/quiz1.rs: -------------------------------------------------------------------------------- 1 | // This is a quiz for the following sections: 2 | // - Variables 3 | // - Functions 4 | // - If 5 | // 6 | // Mary is buying apples. The price of an apple is calculated as follows: 7 | // - An apple costs 2 rustbucks. 8 | // - However, if Mary buys more than 40 apples, the price of each apple in the 9 | // entire order is reduced to only 1 rustbuck! 10 | 11 | // TODO: Write a function that calculates the price of an order of apples given 12 | // the quantity bought. 13 | // fn calculate_price_of_apples(???) -> ??? { ??? } 14 | 15 | fn calculate_price_of_apples(num:u32) -> u32 { 16 | if num > 40 { 17 | num 18 | }else{ 19 | num*2 20 | } 21 | } 22 | 23 | fn main() { 24 | // You can optionally experiment here. 25 | } 26 | 27 | // Don't change the tests! 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn verify_test() { 34 | assert_eq!(calculate_price_of_apples(35), 70); 35 | assert_eq!(calculate_price_of_apples(40), 80); 36 | assert_eq!(calculate_price_of_apples(41), 41); 37 | assert_eq!(calculate_price_of_apples(65), 65); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Rustlings/quizzes/quiz2.rs: -------------------------------------------------------------------------------- 1 | // This is a quiz for the following sections: 2 | // - Strings 3 | // - Vecs 4 | // - Move semantics 5 | // - Modules 6 | // - Enums 7 | // 8 | // Let's build a little machine in the form of a function. As input, we're going 9 | // to give a list of strings and commands. These commands determine what action 10 | // is going to be applied to the string. It can either be: 11 | // - Uppercase the string 12 | // - Trim the string 13 | // - Append "bar" to the string a specified amount of times 14 | // 15 | // The exact form of this will be: 16 | // - The input is going to be a Vector of 2-length tuples, 17 | // the first element is the string, the second one is the command. 18 | // - The output element is going to be a vector of strings. 19 | 20 | enum Command { 21 | Uppercase, 22 | Trim, 23 | Append(usize), 24 | } 25 | 26 | mod my_module { 27 | use super::Command; 28 | 29 | // TODO: Complete the function as described above. 30 | // pub fn transformer(input: ???) -> ??? { ??? } 31 | 32 | pub fn transformer(input:Vec<(String,Command)>) -> Vec { 33 | let mut output: Vec = Vec::new(); 34 | for (i,j) in input { 35 | let new_string = match j { 36 | Command::Trim => i.trim().to_string(), 37 | Command::Uppercase => i.to_uppercase().to_string(), 38 | Command::Append(n) => i+&"bar".repeat(n), 39 | }; 40 | 41 | 42 | output.push(new_string); 43 | } 44 | output 45 | } 46 | } 47 | 48 | fn main() { 49 | // You can optionally experiment here. 50 | } 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | // TODO: What do we need to import to have `transformer` in scope? 55 | // use ???; 56 | use super::my_module::transformer; 57 | use super::Command; 58 | 59 | #[test] 60 | fn it_works() { 61 | let input = vec![ 62 | ("hello".to_string(), Command::Uppercase), 63 | (" all roads lead to rome! ".to_string(), Command::Trim), 64 | ("foo".to_string(), Command::Append(1)), 65 | ("bar".to_string(), Command::Append(5)), 66 | ]; 67 | let output = transformer(input); 68 | 69 | assert_eq!( 70 | output, 71 | [ 72 | "HELLO", 73 | "all roads lead to rome!", 74 | "foobar", 75 | "barbarbarbarbarbar", 76 | ] 77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Rustlings/quizzes/quiz3.rs: -------------------------------------------------------------------------------- 1 | // This quiz tests: 2 | // - Generics 3 | // - Traits 4 | // 5 | // An imaginary magical school has a new report card generation system written 6 | // in Rust! Currently, the system only supports creating report cards where the 7 | // student's grade is represented numerically (e.g. 1.0 -> 5.5). However, the 8 | // school also issues alphabetical grades (A+ -> F-) and needs to be able to 9 | // print both types of report card! 10 | // 11 | // Make the necessary code changes in the struct `ReportCard` and the impl 12 | // block to support alphabetical report cards in addition to numerical ones. 13 | 14 | // TODO: Adjust the struct as described above. 15 | struct ReportCard { 16 | grade: T, 17 | student_name: String, 18 | student_age: u8, 19 | } 20 | 21 | // TODO: Adjust the impl block as described above. 22 | impl ReportCard { 23 | fn print(&self) -> String { 24 | format!( 25 | "{} ({}) - achieved a grade of {}", 26 | &self.student_name, &self.student_age, &self.grade, 27 | ) 28 | } 29 | } 30 | 31 | fn main() { 32 | // You can optionally experiment here. 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn generate_numeric_report_card() { 41 | let report_card = ReportCard { 42 | grade: 2.1, 43 | student_name: "Tom Wriggle".to_string(), 44 | student_age: 12, 45 | }; 46 | assert_eq!( 47 | report_card.print(), 48 | "Tom Wriggle (12) - achieved a grade of 2.1", 49 | ); 50 | } 51 | 52 | #[test] 53 | fn generate_alphabetic_report_card() { 54 | let report_card = ReportCard { 55 | grade: "A+", 56 | student_name: "Gary Plotter".to_string(), 57 | student_age: 11, 58 | }; 59 | assert_eq!( 60 | report_card.print(), 61 | "Gary Plotter (11) - achieved a grade of A+", 62 | ); 63 | } 64 | } 65 | --------------------------------------------------------------------------------