diff --git a/.rustlings-state.txt b/.rustlings-state.txt index e3eec2a..f80a4ed 100644 --- a/.rustlings-state.txt +++ b/.rustlings-state.txt @@ -1,6 +1,6 @@ DON'T EDIT THIS FILE! -structs1 +as_ref_mut intro1 intro2 @@ -31,4 +31,68 @@ move_semantics1 move_semantics2 move_semantics3 move_semantics4 -move_semantics5 \ No newline at end of file +move_semantics5 +structs1 +structs2 +structs3 +enums1 +enums2 +enums3 +strings1 +strings2 +strings3 +strings4 +modules1 +modules2 +modules3 +hashmaps1 +hashmaps2 +hashmaps3 +quiz2 +options1 +options2 +options3 +errors1 +errors2 +errors3 +errors4 +errors5 +errors6 +generics1 +generics2 +traits1 +traits2 +traits3 +traits4 +traits5 +quiz3 +lifetimes1 +lifetimes2 +lifetimes3 +tests1 +tests2 +tests3 +iterators1 +iterators2 +iterators3 +iterators4 +iterators5 +box1 +rc1 +arc1 +cow1 +threads1 +threads2 +threads3 +macros1 +macros2 +macros3 +macros4 +clippy1 +clippy2 +clippy3 +using_as +from_into +from_str +try_from_into +as_ref_mut \ No newline at end of file diff --git a/exercises/07_structs/structs1.rs b/exercises/07_structs/structs1.rs index 959c4c6..e84a90d 100644 --- a/exercises/07_structs/structs1.rs +++ b/exercises/07_structs/structs1.rs @@ -1,12 +1,15 @@ struct ColorRegularStruct { // TODO: Add the fields that the test `regular_structs` expects. // What types should the fields have? What are the minimum and maximum values for RGB colors? + red: u8, + green: u8, + blue: u8, } -struct ColorTupleStruct(/* TODO: Add the fields that the test `tuple_structs` expects */); +struct ColorTupleStruct(u8, u8, u8); #[derive(Debug)] -struct UnitStruct; +struct UnitStruct(); fn main() { // You can optionally experiment here. @@ -19,7 +22,11 @@ mod tests { #[test] fn regular_structs() { // TODO: Instantiate a regular struct. - // let green = + let green = ColorRegularStruct { + red: 0, + green: 255, + blue: 0, + }; assert_eq!(green.red, 0); assert_eq!(green.green, 255); @@ -29,7 +36,7 @@ mod tests { #[test] fn tuple_structs() { // TODO: Instantiate a tuple struct. - // let green = + let green = ColorTupleStruct(0, 255, 0); assert_eq!(green.0, 0); assert_eq!(green.1, 255); @@ -39,7 +46,7 @@ mod tests { #[test] fn unit_structs() { // TODO: Instantiate a unit struct. - // let unit_struct = + let unit_struct = UnitStruct(); let message = format!("{unit_struct:?}s are fun!"); assert_eq!(message, "UnitStructs are fun!"); diff --git a/exercises/07_structs/structs2.rs b/exercises/07_structs/structs2.rs index 79141af..d5c18cb 100644 --- a/exercises/07_structs/structs2.rs +++ b/exercises/07_structs/structs2.rs @@ -34,7 +34,11 @@ mod tests { let order_template = create_order_template(); // TODO: Create your own order using the update syntax and template above! - // let your_order = + let your_order = Order { + name: "Hacker in Rust".to_string(), + count: 1, + ..order_template + }; assert_eq!(your_order.name, "Hacker in Rust"); assert_eq!(your_order.year, order_template.year); diff --git a/exercises/07_structs/structs3.rs b/exercises/07_structs/structs3.rs index 69e5ced..2526a1a 100644 --- a/exercises/07_structs/structs3.rs +++ b/exercises/07_structs/structs3.rs @@ -24,14 +24,16 @@ impl Package { } // TODO: Add the correct return type to the function signature. - fn is_international(&self) { + fn is_international(&self) -> bool { // TODO: Read the tests that use this method to find out when a package // is considered international. + self.sender_country != self.recipient_country } // TODO: Add the correct return type to the function signature. - fn get_fees(&self, cents_per_gram: u32) { + fn get_fees(&self, cents_per_gram: u32) -> u32 { // TODO: Calculate the package's fees. + cents_per_gram * self.weight_in_grams } } diff --git a/exercises/08_enums/enums1.rs b/exercises/08_enums/enums1.rs index c0d0c30..c45ac7a 100644 --- a/exercises/08_enums/enums1.rs +++ b/exercises/08_enums/enums1.rs @@ -1,6 +1,11 @@ #[derive(Debug)] enum Message { // TODO: Define a few types of messages as used below. + Resize, + Move, + Echo, + ChangeColor, + Quit, } fn main() { diff --git a/exercises/08_enums/enums2.rs b/exercises/08_enums/enums2.rs index d70f639..ead7002 100644 --- a/exercises/08_enums/enums2.rs +++ b/exercises/08_enums/enums2.rs @@ -7,6 +7,11 @@ struct Point { #[derive(Debug)] enum Message { // TODO: Define the different variants used below. + Resize { width: usize, height: usize }, + Move(Point), + Echo(String), + ChangeColor(u8, u8, u8), + Quit, } impl Message { diff --git a/exercises/08_enums/enums3.rs b/exercises/08_enums/enums3.rs index cb05f65..1282c40 100644 --- a/exercises/08_enums/enums3.rs +++ b/exercises/08_enums/enums3.rs @@ -46,6 +46,13 @@ impl State { fn process(&mut self, message: Message) { // TODO: Create a match expression to process the different message // variants using the methods defined above. + match message { + Message::Resize { width, height } => self.resize(width, height), + Message::Move(point) => self.move_position(point), + Message::Echo(string) => self.echo(string), + Message::ChangeColor(red, green, blue) => self.change_color(red, green, blue), + Message::Quit => self.quit(), + } } } diff --git a/exercises/09_strings/strings1.rs b/exercises/09_strings/strings1.rs index 6abdbb4..eb70e50 100644 --- a/exercises/09_strings/strings1.rs +++ b/exercises/09_strings/strings1.rs @@ -1,5 +1,5 @@ // TODO: Fix the compiler error without changing the function signature. -fn current_favorite_color() -> String { +fn current_favorite_color() -> &'static str { "blue" } diff --git a/exercises/09_strings/strings2.rs b/exercises/09_strings/strings2.rs index 93d9cb6..2ed89c5 100644 --- a/exercises/09_strings/strings2.rs +++ b/exercises/09_strings/strings2.rs @@ -6,7 +6,7 @@ fn is_a_color_word(attempt: &str) -> bool { fn main() { let word = String::from("green"); // Don't change this line. - if is_a_color_word(word) { + if is_a_color_word(&word) { println!("That is a color word I know!"); } else { println!("That is not a color word I know."); diff --git a/exercises/09_strings/strings3.rs b/exercises/09_strings/strings3.rs index f5e45b0..b7d77f5 100644 --- a/exercises/09_strings/strings3.rs +++ b/exercises/09_strings/strings3.rs @@ -1,13 +1,16 @@ fn trim_me(input: &str) -> &str { // TODO: Remove whitespace from both ends of a string. + input.trim_ascii() } fn compose_me(input: &str) -> String { // TODO: Add " world!" to the string! There are multiple ways to do this. + input.to_owned() + " world!" } fn replace_me(input: &str) -> String { // TODO: Replace "cars" in the string with "balloons". + input.to_owned().replace("cars", "balloons") } fn main() { diff --git a/exercises/09_strings/strings4.rs b/exercises/09_strings/strings4.rs index 4730726..c0b875b 100644 --- a/exercises/09_strings/strings4.rs +++ b/exercises/09_strings/strings4.rs @@ -1,6 +1,3 @@ -// Calls of this function should be replaced with calls of `string_slice` or `string`. -fn placeholder() {} - fn string_slice(arg: &str) { println!("{arg}"); } @@ -13,25 +10,25 @@ fn string(arg: String) { // Your task is to replace `placeholder(…)` with either `string_slice(…)` // or `string(…)` depending on what you think each value is. fn main() { - placeholder("blue"); + string_slice("blue"); // &str - placeholder("red".to_string()); + string("red".to_string()); // String - placeholder(String::from("hi")); + string(String::from("hi")); // String - placeholder("rust is fun!".to_owned()); + string("rust is fun!".to_owned()); // String - placeholder("nice weather".into()); + string("nice weather".into()); // String - placeholder(format!("Interpolation {}", "Station")); + string(format!("Interpolation {}", "Station")); // String // WARNING: This is byte indexing, not character indexing. // Character indexing can be done using `s.chars().nth(INDEX)`. - placeholder(&String::from("abc")[0..1]); + string_slice(&String::from("abc")[0..1]); // &str - placeholder(" hello there ".trim()); + string_slice(" hello there ".trim()); // &str - placeholder("Happy Monday!".replace("Mon", "Tues")); + string("Happy Monday!".replace("Mon", "Tues")); // String - placeholder("mY sHiFt KeY iS sTiCkY".to_lowercase()); + string("mY sHiFt KeY iS sTiCkY".to_lowercase()); // String } diff --git a/exercises/10_modules/modules1.rs b/exercises/10_modules/modules1.rs index d97ab23..81981df 100644 --- a/exercises/10_modules/modules1.rs +++ b/exercises/10_modules/modules1.rs @@ -5,7 +5,7 @@ mod sausage_factory { String::from("Ginger") } - fn make_sausage() { + pub fn make_sausage() { get_secret_recipe(); println!("sausage!"); } diff --git a/exercises/10_modules/modules2.rs b/exercises/10_modules/modules2.rs index 782a70e..3cabbfd 100644 --- a/exercises/10_modules/modules2.rs +++ b/exercises/10_modules/modules2.rs @@ -3,8 +3,8 @@ mod delicious_snacks { // TODO: Add the following two `use` statements after fixing them. - // use self::fruits::PEAR as ???; - // use self::veggies::CUCUMBER as ???; + pub use self::fruits::PEAR as fruit; + pub use self::veggies::CUCUMBER as veggie; mod fruits { pub const PEAR: &str = "Pear"; diff --git a/exercises/10_modules/modules3.rs b/exercises/10_modules/modules3.rs index 691608d..403b7ea 100644 --- a/exercises/10_modules/modules3.rs +++ b/exercises/10_modules/modules3.rs @@ -3,7 +3,7 @@ // TODO: Bring `SystemTime` and `UNIX_EPOCH` from the `std::time` module into // your scope. Bonus style points if you can do it with one line! -// use ???; +use std::time::{SystemTime, UNIX_EPOCH}; fn main() { match SystemTime::now().duration_since(UNIX_EPOCH) { diff --git a/exercises/11_hashmaps/hashmaps1.rs b/exercises/11_hashmaps/hashmaps1.rs index 74001d0..625d023 100644 --- a/exercises/11_hashmaps/hashmaps1.rs +++ b/exercises/11_hashmaps/hashmaps1.rs @@ -8,10 +8,12 @@ use std::collections::HashMap; fn fruit_basket() -> HashMap { // TODO: Declare the hash map. - // let mut basket = + let mut basket = HashMap::::new(); // Two bananas are already given for you :) basket.insert(String::from("banana"), 2); + basket.insert(String::from("apple"), 2); + basket.insert(String::from("mango"), 2); // TODO: Put more fruits in your basket. diff --git a/exercises/11_hashmaps/hashmaps2.rs b/exercises/11_hashmaps/hashmaps2.rs index e9f53fe..c71525f 100644 --- a/exercises/11_hashmaps/hashmaps2.rs +++ b/exercises/11_hashmaps/hashmaps2.rs @@ -32,6 +32,7 @@ fn fruit_basket(basket: &mut HashMap) { // TODO: Insert new fruits if they are not already present in the // basket. Note that you are not allowed to put any type of fruit that's // already present! + basket.entry(fruit).or_insert(1); } } diff --git a/exercises/11_hashmaps/hashmaps3.rs b/exercises/11_hashmaps/hashmaps3.rs index 5b390ab..7d517b8 100644 --- a/exercises/11_hashmaps/hashmaps3.rs +++ b/exercises/11_hashmaps/hashmaps3.rs @@ -31,13 +31,47 @@ fn build_scores_table(results: &str) -> HashMap<&str, TeamScores> { // Keep in mind that goals scored by team 1 will be the number of goals // conceded by team 2. Similarly, goals scored by team 2 will be the // number of goals conceded by team 1. - } + scores + .entry(team_1_name) + .and_modify(|current_team_1_scores| { + current_team_1_scores.goals_scored += team_1_score; + current_team_1_scores.goals_conceded += team_2_score + }) + .or_insert(TeamScores { + goals_scored: team_1_score, + goals_conceded: team_2_score, + }); + scores + .entry(team_2_name) + .and_modify(|current_team_2_scores| { + current_team_2_scores.goals_scored += team_2_score; + current_team_2_scores.goals_conceded += team_1_score + }) + .or_insert(TeamScores { + goals_scored: team_2_score, + goals_conceded: team_1_score, + }); + } scores } fn main() { // You can optionally experiment here. + const RESULTS: &str = "England,France,4,2 +France,Italy,3,1 +Poland,Spain,2,0 +Germany,England,2,1 +England,Spain,1,0"; + + let scores = build_scores_table(RESULTS); + + for (key, value) in &scores { + println!( + "{key}: (scored: {0}, conceeded: {1})", + value.goals_scored, value.goals_conceded + ); + } } #[cfg(test)] @@ -54,9 +88,11 @@ England,Spain,1,0"; fn build_scores() { let scores = build_scores_table(RESULTS); - assert!(["England", "France", "Germany", "Italy", "Poland", "Spain"] - .into_iter() - .all(|team_name| scores.contains_key(team_name))); + assert!( + ["England", "France", "Germany", "Italy", "Poland", "Spain"] + .into_iter() + .all(|team_name| scores.contains_key(team_name)) + ); } #[test] diff --git a/exercises/12_options/options1.rs b/exercises/12_options/options1.rs index d0c412a..9f0bef9 100644 --- a/exercises/12_options/options1.rs +++ b/exercises/12_options/options1.rs @@ -4,6 +4,11 @@ // `hour_of_day` is higher than 23. fn maybe_ice_cream(hour_of_day: u16) -> Option { // TODO: Complete the function body. + match hour_of_day { + 0..22 => Some(5), + 22..=23 => Some(0), + _ => None, + } } fn main() { @@ -18,7 +23,7 @@ mod tests { fn raw_value() { // TODO: Fix this test. How do you get the value contained in the // Option? - let ice_creams = maybe_ice_cream(12); + let ice_creams = maybe_ice_cream(12).unwrap(); assert_eq!(ice_creams, 5); // Don't change this line. } diff --git a/exercises/12_options/options2.rs b/exercises/12_options/options2.rs index 07c27c6..1039d61 100644 --- a/exercises/12_options/options2.rs +++ b/exercises/12_options/options2.rs @@ -10,7 +10,7 @@ mod tests { let optional_target = Some(target); // TODO: Make this an if-let statement whose value is `Some`. - word = optional_target { + if let Some(word) = optional_target { assert_eq!(word, target); } } @@ -29,7 +29,7 @@ mod tests { // TODO: Make this a while-let statement. Remember that `Vec::pop()` // adds another layer of `Option`. You can do nested pattern matching // in if-let and while-let statements. - integer = optional_integers.pop() { + while let Some(Some(integer)) = optional_integers.pop() { assert_eq!(integer, cursor); cursor -= 1; } diff --git a/exercises/12_options/options3.rs b/exercises/12_options/options3.rs index c97b1d3..aecb7a5 100644 --- a/exercises/12_options/options3.rs +++ b/exercises/12_options/options3.rs @@ -9,7 +9,7 @@ fn main() { // TODO: Fix the compiler error by adding something to this match statement. match optional_point { - Some(p) => println!("Coordinates are {},{}", p.x, p.y), + Some(ref p) => println!("Coordinates are {},{}", p.x, p.y), _ => panic!("No match!"), } diff --git a/exercises/13_error_handling/errors1.rs b/exercises/13_error_handling/errors1.rs index e07fddc..fcc4aea 100644 --- a/exercises/13_error_handling/errors1.rs +++ b/exercises/13_error_handling/errors1.rs @@ -4,12 +4,12 @@ // construct to `Option` that can be used to express error conditions. Change // the function signature and body to return `Result` instead // of `Option`. -fn generate_nametag_text(name: String) -> Option { +fn generate_nametag_text(name: String) -> Result { if name.is_empty() { // Empty names aren't allowed - None + Err("Empty names aren't allowed".into()) } else { - Some(format!("Hi! My name is {name}")) + Ok(format!("Hi! My name is {name}")) } } diff --git a/exercises/13_error_handling/errors2.rs b/exercises/13_error_handling/errors2.rs index defe359..3d850f7 100644 --- a/exercises/13_error_handling/errors2.rs +++ b/exercises/13_error_handling/errors2.rs @@ -21,7 +21,7 @@ fn total_cost(item_quantity: &str) -> Result { let cost_per_item = 5; // TODO: Handle the error case as described above. - let qty = item_quantity.parse::(); + let qty = item_quantity.parse::()?; Ok(qty * cost_per_item + processing_fee) } diff --git a/exercises/13_error_handling/errors3.rs b/exercises/13_error_handling/errors3.rs index 8e8c38a..84ac530 100644 --- a/exercises/13_error_handling/errors3.rs +++ b/exercises/13_error_handling/errors3.rs @@ -15,7 +15,7 @@ fn total_cost(item_quantity: &str) -> Result { // TODO: Fix the compiler error by changing the signature and body of the // `main` function. -fn main() { +fn main() -> Result<(), ParseIntError> { let mut tokens = 100; let pretend_user_input = "8"; @@ -24,8 +24,10 @@ fn main() { if cost > tokens { println!("You can't afford that many!"); + Ok(()) } else { tokens -= cost; println!("You now have {tokens} tokens."); + Ok(()) } } diff --git a/exercises/13_error_handling/errors4.rs b/exercises/13_error_handling/errors4.rs index 144fce7..cda83ca 100644 --- a/exercises/13_error_handling/errors4.rs +++ b/exercises/13_error_handling/errors4.rs @@ -11,7 +11,11 @@ impl PositiveNonzeroInteger { fn new(value: i64) -> Result { // TODO: This function shouldn't always return an `Ok`. // Read the tests below to clarify what should be returned. - Ok(Self(value as u64)) + match value { + x if x < 0 => Err(CreationError::Negative), + 0 => Err(CreationError::Zero), + x => Ok(PositiveNonzeroInteger(x as u64)), + } } } diff --git a/exercises/13_error_handling/errors5.rs b/exercises/13_error_handling/errors5.rs index 125779b..405f0dc 100644 --- a/exercises/13_error_handling/errors5.rs +++ b/exercises/13_error_handling/errors5.rs @@ -48,7 +48,7 @@ impl PositiveNonzeroInteger { // TODO: Add the correct return type `Result<(), Box>`. What can we // use to describe both errors? Is there a trait which both errors implement? -fn main() { +fn main() -> Result<(), Box> { let pretend_user_input = "42"; let x: i64 = pretend_user_input.parse()?; println!("output={:?}", PositiveNonzeroInteger::new(x)?); diff --git a/exercises/13_error_handling/errors6.rs b/exercises/13_error_handling/errors6.rs index b1995e0..353b50b 100644 --- a/exercises/13_error_handling/errors6.rs +++ b/exercises/13_error_handling/errors6.rs @@ -25,7 +25,9 @@ impl ParsePosNonzeroError { } // TODO: Add another error conversion function here. - // fn from_parse_int(???) -> Self { ??? } + fn from_parse_int(err: ParseIntError) -> Self { + Self::ParseInt(err) + } } #[derive(PartialEq, Debug)] @@ -43,7 +45,7 @@ impl PositiveNonzeroInteger { fn parse(s: &str) -> Result { // TODO: change this to return an appropriate error instead of panicking // when `parse()` returns an error. - let x: i64 = s.parse().unwrap(); + let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?; Self::new(x).map_err(ParsePosNonzeroError::from_creation) } } diff --git a/exercises/14_generics/generics1.rs b/exercises/14_generics/generics1.rs index 87ed990..7e5571f 100644 --- a/exercises/14_generics/generics1.rs +++ b/exercises/14_generics/generics1.rs @@ -6,7 +6,7 @@ fn main() { // TODO: Fix the compiler error by annotating the type of the vector // `Vec`. Choose `T` as some integer type that can be created from // `u8` and `i8`. - let mut numbers = Vec::new(); + let mut numbers: Vec = Vec::new(); // Don't change the lines below. let n1: u8 = 42; diff --git a/exercises/14_generics/generics2.rs b/exercises/14_generics/generics2.rs index 8908725..ba77625 100644 --- a/exercises/14_generics/generics2.rs +++ b/exercises/14_generics/generics2.rs @@ -1,12 +1,12 @@ // This powerful wrapper provides the ability to store a positive integer value. // TODO: Rewrite it using a generic so that it supports wrapping ANY type. -struct Wrapper { - value: u32, +struct Wrapper { + value: T, } // TODO: Adapt the struct's implementation to be generic over the wrapped value. -impl Wrapper { - fn new(value: u32) -> Self { +impl Wrapper { + fn new(value: T) -> Self { Wrapper { value } } } diff --git a/exercises/15_traits/traits1.rs b/exercises/15_traits/traits1.rs index 85be17e..98eb38a 100644 --- a/exercises/15_traits/traits1.rs +++ b/exercises/15_traits/traits1.rs @@ -6,6 +6,9 @@ trait AppendBar { impl AppendBar for String { // TODO: Implement `AppendBar` for the type `String`. + fn append_bar(self) -> String { + self + "Bar" + } } fn main() { diff --git a/exercises/15_traits/traits2.rs b/exercises/15_traits/traits2.rs index d724dc2..1a93860 100644 --- a/exercises/15_traits/traits2.rs +++ b/exercises/15_traits/traits2.rs @@ -4,6 +4,12 @@ trait AppendBar { // TODO: Implement the trait `AppendBar` for a vector of strings. // `append_bar` should push the string "Bar" into the vector. +impl AppendBar for Vec { + fn append_bar(mut self) -> Self { + self.push("Bar".into()); + self + } +} fn main() { // You can optionally experiment here. diff --git a/exercises/15_traits/traits3.rs b/exercises/15_traits/traits3.rs index c244650..0b800e7 100644 --- a/exercises/15_traits/traits3.rs +++ b/exercises/15_traits/traits3.rs @@ -3,7 +3,9 @@ trait Licensed { // implementors like the two structs below can share that default behavior // without repeating the function. // The default license information should be the string "Default license". - fn licensing_info(&self) -> String; + fn licensing_info(&self) -> String { + "Default license".into() + } } struct SomeSoftware { @@ -28,10 +30,13 @@ mod tests { #[test] fn is_licensing_info_the_same() { let licensing_info = "Default license"; + let some_software = SomeSoftware { version_number: 1 }; + let other_software = OtherSoftware { version_number: "v2.0.0".to_string(), }; + assert_eq!(some_software.licensing_info(), licensing_info); assert_eq!(other_software.licensing_info(), licensing_info); } diff --git a/exercises/15_traits/traits4.rs b/exercises/15_traits/traits4.rs index 80092a6..b23dcdd 100644 --- a/exercises/15_traits/traits4.rs +++ b/exercises/15_traits/traits4.rs @@ -11,7 +11,7 @@ impl Licensed for SomeSoftware {} impl Licensed for OtherSoftware {} // TODO: Fix the compiler error by only changing the signature of this function. -fn compare_license_types(software1: ???, software2: ???) -> bool { +fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool { software1.licensing_info() == software2.licensing_info() } diff --git a/exercises/15_traits/traits5.rs b/exercises/15_traits/traits5.rs index 5b356ac..3f48437 100644 --- a/exercises/15_traits/traits5.rs +++ b/exercises/15_traits/traits5.rs @@ -19,7 +19,7 @@ impl SomeTrait for OtherStruct {} impl OtherTrait for OtherStruct {} // TODO: Fix the compiler error by only changing the signature of this function. -fn some_func(item: ???) -> bool { +fn some_func(item: impl SomeTrait + OtherTrait) -> bool { item.some_function() && item.other_function() } diff --git a/exercises/16_lifetimes/lifetimes1.rs b/exercises/16_lifetimes/lifetimes1.rs index 19e2d39..3559cae 100644 --- a/exercises/16_lifetimes/lifetimes1.rs +++ b/exercises/16_lifetimes/lifetimes1.rs @@ -4,12 +4,8 @@ // not own their own data. What if their owner goes out of scope? // TODO: Fix the compiler error by updating the function signature. -fn longest(x: &str, y: &str) -> &str { - if x.len() > y.len() { - x - } else { - y - } +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + if x.len() > y.len() { x } else { y } } fn main() { diff --git a/exercises/16_lifetimes/lifetimes2.rs b/exercises/16_lifetimes/lifetimes2.rs index de5a5df..b33a7c8 100644 --- a/exercises/16_lifetimes/lifetimes2.rs +++ b/exercises/16_lifetimes/lifetimes2.rs @@ -1,19 +1,15 @@ // Don't change this function. fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { - if x.len() > y.len() { - x - } else { - y - } + if x.len() > y.len() { x } else { y } } fn main() { // TODO: Fix the compiler error by moving one line. let string1 = String::from("long string is long"); + let string2 = String::from("xyz"); let result; { - let string2 = String::from("xyz"); result = longest(&string1, &string2); } println!("The longest string is '{result}'"); diff --git a/exercises/16_lifetimes/lifetimes3.rs b/exercises/16_lifetimes/lifetimes3.rs index 1cc2759..91e3922 100644 --- a/exercises/16_lifetimes/lifetimes3.rs +++ b/exercises/16_lifetimes/lifetimes3.rs @@ -1,9 +1,9 @@ // Lifetimes are also needed when structs hold references. // TODO: Fix the compiler errors about the struct. -struct Book { - author: &str, - title: &str, +struct Book<'a> { + author: &'a str, + title: &'a str, } fn main() { diff --git a/exercises/17_tests/tests1.rs b/exercises/17_tests/tests1.rs index 7529f9f..a832ce0 100644 --- a/exercises/17_tests/tests1.rs +++ b/exercises/17_tests/tests1.rs @@ -13,11 +13,12 @@ fn main() { mod tests { // TODO: Import `is_even`. You can use a wildcard to import everything in // the outer module. + use super::is_even; #[test] fn you_can_assert() { // TODO: Test the function `is_even` with some values. - assert!(); - assert!(); + assert!(is_even(12)); + assert!(!is_even(13)); } } diff --git a/exercises/17_tests/tests2.rs b/exercises/17_tests/tests2.rs index 0c6573e..52faa7b 100644 --- a/exercises/17_tests/tests2.rs +++ b/exercises/17_tests/tests2.rs @@ -15,9 +15,9 @@ mod tests { #[test] fn you_can_assert_eq() { // TODO: Test the function `power_of_2` with some values. - assert_eq!(); - assert_eq!(); - assert_eq!(); - assert_eq!(); + assert_eq!(power_of_2(0), 1); + assert_eq!(power_of_2(1), 2); + assert_eq!(power_of_2(2), 4); + assert_eq!(power_of_2(3), 8); } } diff --git a/exercises/17_tests/tests3.rs b/exercises/17_tests/tests3.rs index 822184e..085bb62 100644 --- a/exercises/17_tests/tests3.rs +++ b/exercises/17_tests/tests3.rs @@ -29,13 +29,14 @@ mod tests { // TODO: This test should check if the rectangle has the size that we // pass to its constructor. let rect = Rectangle::new(10, 20); - assert_eq!(todo!(), 10); // Check width - assert_eq!(todo!(), 20); // Check height + assert_eq!(rect.width, 10); // Check width + assert_eq!(rect.height, 20); // Check height } // TODO: This test should check if the program panics when we try to create // a rectangle with negative width. #[test] + #[should_panic] fn negative_width() { let _rect = Rectangle::new(-10, 10); } @@ -43,6 +44,7 @@ mod tests { // TODO: This test should check if the program panics when we try to create // a rectangle with negative height. #[test] + #[should_panic] fn negative_height() { let _rect = Rectangle::new(10, -10); } diff --git a/exercises/18_iterators/iterators1.rs b/exercises/18_iterators/iterators1.rs index ca937ed..71d8112 100644 --- a/exercises/18_iterators/iterators1.rs +++ b/exercises/18_iterators/iterators1.rs @@ -13,13 +13,13 @@ mod tests { let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"]; // TODO: Create an iterator over the array. - let mut fav_fruits_iterator = todo!(); + let mut fav_fruits_iterator = my_fav_fruits.iter(); assert_eq!(fav_fruits_iterator.next(), Some(&"banana")); - assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()` + assert_eq!(fav_fruits_iterator.next(), Some(&"custard apple")); // TODO: Replace `todo!()` assert_eq!(fav_fruits_iterator.next(), Some(&"avocado")); - assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()` + assert_eq!(fav_fruits_iterator.next(), Some(&"peach")); // TODO: Replace `todo!()` assert_eq!(fav_fruits_iterator.next(), Some(&"raspberry")); - assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()` + assert_eq!(fav_fruits_iterator.next(), None); // TODO: Replace `todo!()` } } diff --git a/exercises/18_iterators/iterators2.rs b/exercises/18_iterators/iterators2.rs index 5903e65..093c709 100644 --- a/exercises/18_iterators/iterators2.rs +++ b/exercises/18_iterators/iterators2.rs @@ -5,9 +5,10 @@ // "hello" -> "Hello" fn capitalize_first(input: &str) -> String { let mut chars = input.chars(); + match chars.next() { None => String::new(), - Some(first) => todo!(), + Some(first) => first.to_uppercase().chain(chars).collect(), } } @@ -15,14 +16,14 @@ fn capitalize_first(input: &str) -> String { // Return a vector of strings. // ["hello", "world"] -> ["Hello", "World"] fn capitalize_words_vector(words: &[&str]) -> Vec { - // ??? + words.iter().map(|word| capitalize_first(word)).collect() } // TODO: Apply the `capitalize_first` function again to a slice of string // slices. Return a single string. // ["hello", " ", "world"] -> "Hello World" fn capitalize_words_string(words: &[&str]) -> String { - // ??? + words.iter().map(|word| capitalize_first(word)).collect() } fn main() { diff --git a/exercises/18_iterators/iterators3.rs b/exercises/18_iterators/iterators3.rs index dce0905..55f8292 100644 --- a/exercises/18_iterators/iterators3.rs +++ b/exercises/18_iterators/iterators3.rs @@ -11,21 +11,36 @@ enum DivisionError { // TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`. // Otherwise, return a suitable error. fn divide(a: i64, b: i64) -> Result { - todo!(); + match (a, b) { + (_, 0) => Err(DivisionError::DivideByZero), + (a, b) if a == i64::MIN && b == -1 => Err(DivisionError::IntegerOverflow), + (a, b) if a % b != 0 => Err(DivisionError::NotDivisible), + (a, b) => Ok(a / b), + } } // TODO: Add the correct return type and complete the function body. // Desired output: `Ok([1, 11, 1426, 3])` -fn result_with_list() { +fn result_with_list() -> Result, DivisionError> { let numbers = [27, 297, 38502, 81]; - let division_results = numbers.into_iter().map(|n| divide(n, 27)); + let result: Vec = numbers + .into_iter() + .map(|n| divide(n, 27)) + .collect::, DivisionError>>()?; + + Ok(result) } // TODO: Add the correct return type and complete the function body. // Desired output: `[Ok(1), Ok(11), Ok(1426), Ok(3)]` -fn list_of_results() { +fn list_of_results() -> Vec> { let numbers = [27, 297, 38502, 81]; - let division_results = numbers.into_iter().map(|n| divide(n, 27)); + let division_results: Vec> = numbers + .into_iter() + .map(|n| divide(n, 27)) + .collect::>>(); + + division_results } fn main() { diff --git a/exercises/18_iterators/iterators4.rs b/exercises/18_iterators/iterators4.rs index c296f0e..c6efd9b 100644 --- a/exercises/18_iterators/iterators4.rs +++ b/exercises/18_iterators/iterators4.rs @@ -10,6 +10,7 @@ fn factorial(num: u64) -> u64 { // - additional variables // For an extra challenge, don't use: // - recursion + (1..=num).fold(1, |acc, e| acc * e) } fn main() { diff --git a/exercises/18_iterators/iterators5.rs b/exercises/18_iterators/iterators5.rs index 7e434cc..6b09665 100644 --- a/exercises/18_iterators/iterators5.rs +++ b/exercises/18_iterators/iterators5.rs @@ -28,6 +28,9 @@ fn count_for(map: &HashMap, value: Progress) -> usize { fn count_iterator(map: &HashMap, value: Progress) -> usize { // `map` is a hash map with `String` keys and `Progress` values. // map = { "variables1": Complete, "from_str": None, … } + map.values() + .filter(|excercise| **excercise == value) + .count() } fn count_collection_for(collection: &[HashMap], value: Progress) -> usize { @@ -48,6 +51,11 @@ fn count_collection_iterator(collection: &[HashMap], value: Pr // `collection` is a slice of hash maps. // collection = [{ "variables1": Complete, "from_str": None, … }, // { "variables2": Complete, … }, … ] + collection + .iter() + .flatten() + .filter(|excercise| *excercise.1 == value) + .count() } fn main() { diff --git a/exercises/19_smart_pointers/arc1.rs b/exercises/19_smart_pointers/arc1.rs index 6bb860f..a5b9467 100644 --- a/exercises/19_smart_pointers/arc1.rs +++ b/exercises/19_smart_pointers/arc1.rs @@ -23,13 +23,13 @@ fn main() { let numbers: Vec<_> = (0..100u32).collect(); // TODO: Define `shared_numbers` by using `Arc`. - // let shared_numbers = ???; + let shared_numbers = Arc::new(numbers); let mut join_handles = Vec::new(); for offset in 0..8 { // TODO: Define `child_numbers` using `shared_numbers`. - // let child_numbers = ???; + let child_numbers = Arc::clone(&shared_numbers); let handle = thread::spawn(move || { let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum(); diff --git a/exercises/19_smart_pointers/box1.rs b/exercises/19_smart_pointers/box1.rs index d70e1c3..68ea288 100644 --- a/exercises/19_smart_pointers/box1.rs +++ b/exercises/19_smart_pointers/box1.rs @@ -12,18 +12,18 @@ // TODO: Use a `Box` in the enum definition to make the code compile. #[derive(PartialEq, Debug)] enum List { - Cons(i32, List), + Cons(i32, Box), Nil, } // TODO: Create an empty cons list. fn create_empty_list() -> List { - todo!() + List::Nil } // TODO: Create a non-empty cons list. fn create_non_empty_list() -> List { - todo!() + List::Cons(64, Box::new(List::Nil)) } fn main() { diff --git a/exercises/19_smart_pointers/cow1.rs b/exercises/19_smart_pointers/cow1.rs index 1566500..0c9c1d6 100644 --- a/exercises/19_smart_pointers/cow1.rs +++ b/exercises/19_smart_pointers/cow1.rs @@ -39,7 +39,7 @@ mod tests { let mut input = Cow::from(&vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Borrowed(_))); } #[test] @@ -52,7 +52,7 @@ mod tests { let mut input = Cow::from(vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Owned(_))); } #[test] @@ -64,6 +64,6 @@ mod tests { let mut input = Cow::from(vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Owned(_))); } } diff --git a/exercises/19_smart_pointers/rc1.rs b/exercises/19_smart_pointers/rc1.rs index ecd3438..ffce6e5 100644 --- a/exercises/19_smart_pointers/rc1.rs +++ b/exercises/19_smart_pointers/rc1.rs @@ -60,17 +60,17 @@ mod tests { jupiter.details(); // TODO - let saturn = Planet::Saturn(Rc::new(Sun)); + let saturn = Planet::Saturn(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 7 references saturn.details(); // TODO - let uranus = Planet::Uranus(Rc::new(Sun)); + let uranus = Planet::Uranus(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 8 references uranus.details(); // TODO - let neptune = Planet::Neptune(Rc::new(Sun)); + let neptune = Planet::Neptune(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 9 references neptune.details(); @@ -91,13 +91,13 @@ mod tests { drop(mars); println!("reference count = {}", Rc::strong_count(&sun)); // 4 references - // TODO + drop(earth); println!("reference count = {}", Rc::strong_count(&sun)); // 3 references - // TODO + drop(venus); println!("reference count = {}", Rc::strong_count(&sun)); // 2 references - // TODO + drop(mercury); println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference assert_eq!(Rc::strong_count(&sun), 1); diff --git a/exercises/20_threads/threads1.rs b/exercises/20_threads/threads1.rs index dbc64b1..a686224 100644 --- a/exercises/20_threads/threads1.rs +++ b/exercises/20_threads/threads1.rs @@ -20,10 +20,12 @@ fn main() { handles.push(handle); } - let mut results = Vec::new(); + let mut results: Vec<_> = Vec::<_>::new(); + for handle in handles { // TODO: Collect the results of all threads into the `results` vector. // Use the `JoinHandle` struct which is returned by `thread::spawn`. + results.push(handle.join().unwrap()) } if results.len() != 10 { diff --git a/exercises/20_threads/threads2.rs b/exercises/20_threads/threads2.rs index 7020cb9..b6a100b 100644 --- a/exercises/20_threads/threads2.rs +++ b/exercises/20_threads/threads2.rs @@ -2,24 +2,31 @@ // work. But this time, the spawned threads need to be in charge of updating a // shared value: `JobStatus.jobs_done` -use std::{sync::Arc, thread, time::Duration}; +use std::{ + sync::{Arc, Mutex}, + thread, + time::Duration, +}; +#[derive(Debug)] struct JobStatus { jobs_done: u32, } fn main() { // TODO: `Arc` isn't enough if you want a **mutable** shared state. - let status = Arc::new(JobStatus { jobs_done: 0 }); + let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 })); let mut handles = Vec::new(); for _ in 0..10 { let status_shared = Arc::clone(&status); + let handle = thread::spawn(move || { thread::sleep(Duration::from_millis(250)); // TODO: You must take an action before you update a shared value. - status_shared.jobs_done += 1; + let mut acquired_status = status_shared.lock().unwrap(); + acquired_status.jobs_done += 1; }); handles.push(handle); } @@ -30,5 +37,7 @@ fn main() { } // TODO: Print the value of `JobStatus.jobs_done`. - println!("Jobs done: {}", todo!()); + let mutex = Arc::try_unwrap(status).unwrap(); + let job_status = mutex.into_inner().unwrap(); + println!("Jobs done: {}", job_status.jobs_done); } diff --git a/exercises/20_threads/threads3.rs b/exercises/20_threads/threads3.rs index 6d16bd9..994d985 100644 --- a/exercises/20_threads/threads3.rs +++ b/exercises/20_threads/threads3.rs @@ -17,18 +17,23 @@ impl Queue { fn send_tx(q: Queue, tx: mpsc::Sender) { // TODO: We want to send `tx` to both threads. But currently, it is moved // into the first thread. How could you solve this problem? + + let transmission = tx.clone(); + thread::spawn(move || { for val in q.first_half { println!("Sending {val:?}"); - tx.send(val).unwrap(); + transmission.send(val).unwrap(); thread::sleep(Duration::from_millis(250)); } }); + let transmission = tx.clone(); + thread::spawn(move || { for val in q.second_half { println!("Sending {val:?}"); - tx.send(val).unwrap(); + transmission.send(val).unwrap(); thread::sleep(Duration::from_millis(250)); } }); diff --git a/exercises/21_macros/macros1.rs b/exercises/21_macros/macros1.rs index fb3c3ff..fb550f9 100644 --- a/exercises/21_macros/macros1.rs +++ b/exercises/21_macros/macros1.rs @@ -6,5 +6,5 @@ macro_rules! my_macro { fn main() { // TODO: Fix the macro call. - my_macro(); + my_macro!(); } diff --git a/exercises/21_macros/macros2.rs b/exercises/21_macros/macros2.rs index 2d9dec7..f310a0b 100644 --- a/exercises/21_macros/macros2.rs +++ b/exercises/21_macros/macros2.rs @@ -1,10 +1,10 @@ -fn main() { - my_macro!(); -} - // TODO: Fix the compiler error by moving the whole definition of this macro. macro_rules! my_macro { () => { println!("Check out my macro!"); }; } + +fn main() { + my_macro!(); +} diff --git a/exercises/21_macros/macros3.rs b/exercises/21_macros/macros3.rs index 9537494..7b2e72b 100644 --- a/exercises/21_macros/macros3.rs +++ b/exercises/21_macros/macros3.rs @@ -1,6 +1,7 @@ // TODO: Fix the compiler error without taking the macro definition out of this // module. mod macros { + #[macro_export] macro_rules! my_macro { () => { println!("Check out my macro!"); diff --git a/exercises/21_macros/macros4.rs b/exercises/21_macros/macros4.rs index 9d77f6a..3396f0d 100644 --- a/exercises/21_macros/macros4.rs +++ b/exercises/21_macros/macros4.rs @@ -3,7 +3,7 @@ macro_rules! my_macro { () => { println!("Check out my macro!"); - } + }; ($val:expr) => { println!("Look at this other macro: {}", $val); } diff --git a/exercises/22_clippy/clippy1.rs b/exercises/22_clippy/clippy1.rs index 7165da4..4c4b52a 100644 --- a/exercises/22_clippy/clippy1.rs +++ b/exercises/22_clippy/clippy1.rs @@ -6,7 +6,7 @@ fn main() { // TODO: Fix the Clippy lint in this line. - let pi = 3.14; + let pi = std::f32::consts::PI; let radius: f32 = 5.0; let area = pi * radius.powi(2); diff --git a/exercises/22_clippy/clippy2.rs b/exercises/22_clippy/clippy2.rs index 8cfe6f8..4605ee9 100644 --- a/exercises/22_clippy/clippy2.rs +++ b/exercises/22_clippy/clippy2.rs @@ -1,8 +1,9 @@ fn main() { let mut res = 42; let option = Some(12); + // TODO: Fix the Clippy lint. - for x in option { + if let Some(x) = option { res += x; } diff --git a/exercises/22_clippy/clippy3.rs b/exercises/22_clippy/clippy3.rs index 7a3cb39..276d027 100644 --- a/exercises/22_clippy/clippy3.rs +++ b/exercises/22_clippy/clippy3.rs @@ -7,23 +7,23 @@ fn main() { let my_option: Option<&str> = None; // Assume that you don't know the value of `my_option`. // In the case of `Some`, we want to print its value. - if my_option.is_none() { - println!("{}", my_option.unwrap()); + if let Some(my_option) = my_option { + println!("{}", my_option); } let my_arr = &[ - -1, -2, -3 + -1, -2, -3, -4, -5, -6 ]; println!("My array! Here it is: {my_arr:?}"); - let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5); + let my_empty_vec = (); + vec![1, 2, 3, 4, 5].resize(0, 5); println!("This Vec is empty, see? {my_empty_vec:?}"); let mut value_a = 45; let mut value_b = 66; // Let's swap these two! - value_a = value_b; - value_b = value_a; + std::mem::swap(&mut value_a, &mut value_b); println!("value a: {value_a}; value b: {value_b}"); } diff --git a/exercises/23_conversions/as_ref_mut.rs b/exercises/23_conversions/as_ref_mut.rs index d7892dd..c13b3c7 100644 --- a/exercises/23_conversions/as_ref_mut.rs +++ b/exercises/23_conversions/as_ref_mut.rs @@ -5,20 +5,22 @@ // Obtain the number of bytes (not characters) in the given argument // (`.len()` returns the number of bytes in a string). // TODO: Add the `AsRef` trait appropriately as a trait bound. -fn byte_counter(arg: T) -> usize { +fn byte_counter>(arg: T) -> usize { arg.as_ref().len() } // Obtain the number of characters (not bytes) in the given argument. // TODO: Add the `AsRef` trait appropriately as a trait bound. -fn char_counter(arg: T) -> usize { +fn char_counter>(arg: T) -> usize { arg.as_ref().chars().count() } // Squares a number using `as_mut()`. // TODO: Add the appropriate trait bound. -fn num_sq(arg: &mut T) { +fn num_sq>(arg: &mut T) { // TODO: Implement the function body. + let val = *arg.as_mut(); + *arg.as_mut() = val * val; } fn main() { diff --git a/exercises/23_conversions/from_into.rs b/exercises/23_conversions/from_into.rs index bc2783a..97b1caf 100644 --- a/exercises/23_conversions/from_into.rs +++ b/exercises/23_conversions/from_into.rs @@ -34,7 +34,18 @@ impl Default for Person { // 5. Parse the second element from the split operation into a `u8` as the age. // 6. If parsing the age fails, return the default of `Person`. impl From<&str> for Person { - fn from(s: &str) -> Self {} + fn from(s: &str) -> Self { + match s.split(",").collect::>().as_slice() { + [name, age] if (!name.is_empty() && !age.is_empty()) => match age.parse::() { + Ok(age) => Person { + name: name.to_string(), + age, + }, + Err(_) => Person::default(), + }, + _ => Person::default(), + } + } } fn main() { diff --git a/exercises/23_conversions/from_str.rs b/exercises/23_conversions/from_str.rs index ec6d3fd..e2682b6 100644 --- a/exercises/23_conversions/from_str.rs +++ b/exercises/23_conversions/from_str.rs @@ -41,7 +41,19 @@ enum ParsePersonError { impl FromStr for Person { type Err = ParsePersonError; - fn from_str(s: &str) -> Result {} + fn from_str(s: &str) -> Result { + match s.split(",").collect::>().as_slice() { + [name, age] if (!name.is_empty()) => match age.parse::() { + Ok(age) => Ok(Person { + name: name.to_string(), + age, + }), + Err(err) => Err(ParsePersonError::ParseInt(err)), + }, + ["", _] => Err(ParsePersonError::NoName), + _ => Err(ParsePersonError::BadLen), + } + } } fn main() { diff --git a/exercises/23_conversions/try_from_into.rs b/exercises/23_conversions/try_from_into.rs index f3ae80a..b041f31 100644 --- a/exercises/23_conversions/try_from_into.rs +++ b/exercises/23_conversions/try_from_into.rs @@ -28,14 +28,45 @@ enum IntoColorError { impl TryFrom<(i16, i16, i16)> for Color { type Error = IntoColorError; - fn try_from(tuple: (i16, i16, i16)) -> Result {} + fn try_from(tuple: (i16, i16, i16)) -> Result { + match tuple { + (red, green, blue) + if (0..=255).contains(&red) + && (0..=255).contains(&green) + && (0..=255).contains(&blue) => + { + Ok(Color { + red: red as u8, + green: green as u8, + blue: blue as u8, + }) + } + _ => Err(IntoColorError::IntConversion), + } + } } // TODO: Array implementation. impl TryFrom<[i16; 3]> for Color { type Error = IntoColorError; - fn try_from(arr: [i16; 3]) -> Result {} + fn try_from(arr: [i16; 3]) -> Result { + match arr.as_slice() { + [red, green, blue] => { + if (0..=255).contains(red) && (0..=255).contains(green) && (0..=255).contains(blue) + { + Ok(Color { + red: *red as u8, + green: *green as u8, + blue: *blue as u8, + }) + } else { + Err(IntoColorError::IntConversion) + } + } + _ => Err(IntoColorError::BadLen), + } + } } // TODO: Slice implementation. @@ -43,7 +74,23 @@ impl TryFrom<[i16; 3]> for Color { impl TryFrom<&[i16]> for Color { type Error = IntoColorError; - fn try_from(slice: &[i16]) -> Result {} + fn try_from(slice: &[i16]) -> Result { + match slice { + [red, green, blue] => { + if (0..=255).contains(red) && (0..=255).contains(green) && (0..=255).contains(blue) + { + Ok(Color { + red: *red as u8, + green: *green as u8, + blue: *blue as u8, + }) + } else { + Err(IntoColorError::IntConversion) + } + } + _ => Err(IntoColorError::BadLen), + } + } } fn main() { diff --git a/exercises/23_conversions/using_as.rs b/exercises/23_conversions/using_as.rs index c131d1f..dff453b 100644 --- a/exercises/23_conversions/using_as.rs +++ b/exercises/23_conversions/using_as.rs @@ -5,7 +5,7 @@ fn average(values: &[f64]) -> f64 { let total = values.iter().sum::(); // TODO: Make a conversion before dividing. - total / values.len() + total / values.len() as f64 } fn main() { diff --git a/exercises/quizzes/quiz2.rs b/exercises/quizzes/quiz2.rs index 2cddba9..d12cafd 100644 --- a/exercises/quizzes/quiz2.rs +++ b/exercises/quizzes/quiz2.rs @@ -27,7 +27,21 @@ mod my_module { use super::Command; // TODO: Complete the function as described above. - // pub fn transformer(input: ???) -> ??? { ??? } + pub fn transformer(input: Vec<(String, Command)>) -> Vec { + let mut output: Vec = Vec::new(); + + for (string, command) in input { + match command { + Command::Uppercase => output.push(string.to_uppercase()), + Command::Trim => output.push(string.trim().into()), + Command::Append(number_of_times_bar_will_be_added) => { + output.push(string + &"bar".repeat(number_of_times_bar_will_be_added)) + } + } + } + + output + } } fn main() { @@ -37,8 +51,8 @@ fn main() { #[cfg(test)] mod tests { // TODO: What do we need to import to have `transformer` in scope? - // use ???; use super::Command; + use super::my_module::transformer; #[test] fn it_works() { diff --git a/exercises/quizzes/quiz3.rs b/exercises/quizzes/quiz3.rs index c877c5f..4fc72ce 100644 --- a/exercises/quizzes/quiz3.rs +++ b/exercises/quizzes/quiz3.rs @@ -10,16 +10,17 @@ // // Make the necessary code changes in the struct `ReportCard` and the impl // block to support alphabetical report cards in addition to numerical ones. +use std::fmt::Display; // TODO: Adjust the struct as described above. -struct ReportCard { - grade: f32, +struct ReportCard { + grade: G, student_name: String, student_age: u8, } // TODO: Adjust the impl block as described above. -impl ReportCard { +impl ReportCard { fn print(&self) -> String { format!( "{} ({}) - achieved a grade of {}",