diff options
| author | mokou <mokou@fastmail.com> | 2022-07-15 14:31:49 +0200 |
|---|---|---|
| committer | mokou <mokou@fastmail.com> | 2022-07-15 14:31:49 +0200 |
| commit | c791cf4232fbfc313279b19b483c1adbca1c6862 (patch) | |
| tree | 655ad6c9d33dab11dfd70f28d0ec29d03749a70b /exercises | |
| parent | f1c4caa37fe5027d121aec6433dee85433d9329d (diff) | |
| parent | c265b681b188ea21b3f8585e65ea363fc02c4b50 (diff) | |
Merge branch '5.0-dev'
Diffstat (limited to 'exercises')
126 files changed, 867 insertions, 702 deletions
diff --git a/exercises/advanced_errors/advanced_errs1.rs b/exercises/advanced_errors/advanced_errs1.rs deleted file mode 100644 index 4bc7b63..0000000 --- a/exercises/advanced_errors/advanced_errs1.rs +++ /dev/null @@ -1,98 +0,0 @@ -// advanced_errs1.rs - -// Remember back in errors6, we had multiple mapping functions so that we -// could translate lower-level errors into our custom error type using -// `map_err()`? What if we could use the `?` operator directly instead? - -// Make this code compile! Execute `rustlings hint advanced_errs1` for -// hints :) - -// I AM NOT DONE - -use std::num::ParseIntError; -use std::str::FromStr; - -// This is a custom error type that we will be using in the `FromStr` -// implementation. -#[derive(PartialEq, Debug)] -enum ParsePosNonzeroError { - Creation(CreationError), - ParseInt(ParseIntError), -} - -impl From<CreationError> for ParsePosNonzeroError { - fn from(e: CreationError) -> Self { - // TODO: complete this implementation so that the `?` operator will - // work for `CreationError` - } -} - -// TODO: implement another instance of the `From` trait here so that the -// `?` operator will work in the other place in the `FromStr` -// implementation below. - -// Don't change anything below this line. - -impl FromStr for PositiveNonzeroInteger { - type Err = ParsePosNonzeroError; - fn from_str(s: &str) -> Result<PositiveNonzeroInteger, Self::Err> { - let x: i64 = s.parse()?; - Ok(PositiveNonzeroInteger::new(x)?) - } -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { - match value { - x if x < 0 => Err(CreationError::Negative), - x if x == 0 => Err(CreationError::Zero), - x => Ok(PositiveNonzeroInteger(x as u64)), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_error() { - // We can't construct a ParseIntError, so we have to pattern match. - assert!(matches!( - PositiveNonzeroInteger::from_str("not a number"), - Err(ParsePosNonzeroError::ParseInt(_)) - )); - } - - #[test] - fn test_negative() { - assert_eq!( - PositiveNonzeroInteger::from_str("-555"), - Err(ParsePosNonzeroError::Creation(CreationError::Negative)) - ); - } - - #[test] - fn test_zero() { - assert_eq!( - PositiveNonzeroInteger::from_str("0"), - Err(ParsePosNonzeroError::Creation(CreationError::Zero)) - ); - } - - #[test] - fn test_positive() { - let x = PositiveNonzeroInteger::new(42); - assert!(x.is_ok()); - assert_eq!(PositiveNonzeroInteger::from_str("42"), Ok(x.unwrap())); - } -} diff --git a/exercises/advanced_errors/advanced_errs2.rs b/exercises/advanced_errors/advanced_errs2.rs deleted file mode 100644 index 54e669f..0000000 --- a/exercises/advanced_errors/advanced_errs2.rs +++ /dev/null @@ -1,202 +0,0 @@ -// advanced_errs2.rs - -// This exercise demonstrates a few traits that are useful for custom error -// types to implement, especially so that other code can consume the custom -// error type more usefully. - -// Make this compile, and make the tests pass! -// Execute `rustlings hint advanced_errs2` for hints. - -// Steps: -// 1. Implement a missing trait so that `main()` will compile. -// 2. Complete the partial implementation of `From` for -// `ParseClimateError`. -// 3. Handle the missing error cases in the `FromStr` implementation for -// `Climate`. -// 4. Complete the partial implementation of `Display` for -// `ParseClimateError`. - -// I AM NOT DONE - -use std::error::Error; -use std::fmt::{self, Display, Formatter}; -use std::num::{ParseFloatError, ParseIntError}; -use std::str::FromStr; - -// This is the custom error type that we will be using for the parser for -// `Climate`. -#[derive(Debug, PartialEq)] -enum ParseClimateError { - Empty, - BadLen, - NoCity, - ParseInt(ParseIntError), - ParseFloat(ParseFloatError), -} - -// This `From` implementation allows the `?` operator to work on -// `ParseIntError` values. -impl From<ParseIntError> for ParseClimateError { - fn from(e: ParseIntError) -> Self { - Self::ParseInt(e) - } -} - -// This `From` implementation allows the `?` operator to work on -// `ParseFloatError` values. -impl From<ParseFloatError> for ParseClimateError { - fn from(e: ParseFloatError) -> Self { - // TODO: Complete this function - } -} - -// TODO: Implement a missing trait so that `main()` below will compile. It -// is not necessary to implement any methods inside the missing trait. - -// The `Display` trait allows for other code to obtain the error formatted -// as a user-visible string. -impl Display for ParseClimateError { - // TODO: Complete this function so that it produces the correct strings - // for each error variant. - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - // Imports the variants to make the following code more compact. - use ParseClimateError::*; - match self { - NoCity => write!(f, "no city name"), - ParseFloat(e) => write!(f, "error parsing temperature: {}", e), - } - } -} - -#[derive(Debug, PartialEq)] -struct Climate { - city: String, - year: u32, - temp: f32, -} - -// Parser for `Climate`. -// 1. Split the input string into 3 fields: city, year, temp. -// 2. Return an error if the string is empty or has the wrong number of -// fields. -// 3. Return an error if the city name is empty. -// 4. Parse the year as a `u32` and return an error if that fails. -// 5. Parse the temp as a `f32` and return an error if that fails. -// 6. Return an `Ok` value containing the completed `Climate` value. -impl FromStr for Climate { - type Err = ParseClimateError; - // TODO: Complete this function by making it handle the missing error - // cases. - fn from_str(s: &str) -> Result<Self, Self::Err> { - let v: Vec<_> = s.split(',').collect(); - let (city, year, temp) = match &v[..] { - [city, year, temp] => (city.to_string(), year, temp), - _ => return Err(ParseClimateError::BadLen), - }; - let year: u32 = year.parse()?; - let temp: f32 = temp.parse()?; - Ok(Climate { city, year, temp }) - } -} - -// Don't change anything below this line (other than to enable ignored -// tests). - -fn main() -> Result<(), Box<dyn Error>> { - println!("{:?}", "Hong Kong,1999,25.7".parse::<Climate>()?); - println!("{:?}", "".parse::<Climate>()?); - Ok(()) -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn test_empty() { - let res = "".parse::<Climate>(); - assert_eq!(res, Err(ParseClimateError::Empty)); - assert_eq!(res.unwrap_err().to_string(), "empty input"); - } - #[test] - fn test_short() { - let res = "Boston,1991".parse::<Climate>(); - assert_eq!(res, Err(ParseClimateError::BadLen)); - assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); - } - #[test] - fn test_long() { - let res = "Paris,1920,17.2,extra".parse::<Climate>(); - assert_eq!(res, Err(ParseClimateError::BadLen)); - assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); - } - #[test] - fn test_no_city() { - let res = ",1997,20.5".parse::<Climate>(); - assert_eq!(res, Err(ParseClimateError::NoCity)); - assert_eq!(res.unwrap_err().to_string(), "no city name"); - } - #[test] - fn test_parse_int_neg() { - let res = "Barcelona,-25,22.3".parse::<Climate>(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseInt(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing year: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_int_bad() { - let res = "Beijing,foo,15.0".parse::<Climate>(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseInt(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing year: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_float() { - let res = "Manila,2001,bar".parse::<Climate>(); - assert!(matches!(res, Err(ParseClimateError::ParseFloat(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseFloat(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing temperature: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_good() { - let res = "Munich,2015,23.1".parse::<Climate>(); - assert_eq!( - res, - Ok(Climate { - city: "Munich".to_string(), - year: 2015, - temp: 23.1, - }) - ); - } - #[test] - #[ignore] - fn test_downcast() { - let res = "São Paulo,-21,28.5".parse::<Climate>(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - let inner: Option<&(dyn Error + 'static)> = err.source(); - assert!(inner.is_some()); - assert!(inner.unwrap().is::<ParseIntError>()); - } -} diff --git a/exercises/advanced_errors/mod.rs b/exercises/advanced_errors/mod.rs deleted file mode 100644 index e33fb80..0000000 --- a/exercises/advanced_errors/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod advanced_errs1; -mod advanced_errs2; diff --git a/exercises/clippy/clippy1.rs b/exercises/clippy/clippy1.rs index c5f84a9..bad4689 100644 --- a/exercises/clippy/clippy1.rs +++ b/exercises/clippy/clippy1.rs @@ -4,7 +4,7 @@ // // For these exercises the code will fail to compile when there are clippy warnings // check clippy's suggestions from the output to solve the exercise. -// Execute `rustlings hint clippy1` for hints :) +// Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/clippy/clippy2.rs b/exercises/clippy/clippy2.rs index 37af9ed..dac40db 100644 --- a/exercises/clippy/clippy2.rs +++ b/exercises/clippy/clippy2.rs @@ -1,5 +1,5 @@ // clippy2.rs -// Make me compile! Execute `rustlings hint clippy2` for hints :) +// Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/clippy/clippy3.rs b/exercises/clippy/clippy3.rs new file mode 100644 index 0000000..b0159eb --- /dev/null +++ b/exercises/clippy/clippy3.rs @@ -0,0 +1,28 @@ +// clippy3.rs +// Here's a couple more easy Clippy fixes, so you can see its utility. + +// I AM NOT DONE + +#[allow(unused_variables, unused_assignments)] +fn main() { + let my_option: Option<()> = None; + if my_option.is_none() { + my_option.unwrap(); + } + + let my_arr = &[ + -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); + 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; + println!("value a: {}; value b: {}", value_a, value_b); +} diff --git a/exercises/clippy/mod.rs b/exercises/clippy/mod.rs deleted file mode 100644 index 689dc95..0000000 --- a/exercises/clippy/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod clippy1; -mod clippy2; diff --git a/exercises/collections/README.md b/exercises/collections/README.md deleted file mode 100644 index b6d62ac..0000000 --- a/exercises/collections/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Collections - -Rust’s standard library includes a number of very useful data -structures called collections. Most other data types represent one -specific value, but collections can contain multiple values. Unlike -the built-in array and tuple types, the data these collections point -to is stored on the heap, which means the amount of data does not need -to be known at compile time and can grow or shrink as the program -runs. - -This exercise will get you familiar with two fundamental data -structures that are used very often in Rust programs: - -* A *vector* allows you to store a variable number of values next to - each other. -* A *hash map* allows you to associate a value with a particular key. - You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map), - [*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages. - -## Further information - -- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html) -- [Storing Keys with Associated Values in Hash Maps](https://doc.rust-lang.org/book/ch08-03-hash-maps.html) diff --git a/exercises/collections/mod.rs b/exercises/collections/mod.rs deleted file mode 100644 index f46c142..0000000 --- a/exercises/collections/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod hashmap1; -mod hashmap2; -mod vec1; -mod vec2; diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs index 84f4a60..9f47973 100644 --- a/exercises/conversions/as_ref_mut.rs +++ b/exercises/conversions/as_ref_mut.rs @@ -1,6 +1,7 @@ // AsRef and AsMut allow for cheap reference-to-reference conversions. // Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html // and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively. +// Execute `rustlings hint as_ref_mut` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -16,10 +17,10 @@ fn char_counter<T>(arg: T) -> usize { arg.as_ref().chars().count() } -fn main() { - let s = "Café au lait"; - println!("{}", char_counter(s)); - println!("{}", byte_counter(s)); +// Squares a number using AsMut. Add the trait bound as is appropriate and +// implement the function body. +fn num_sq<T>(arg: &mut T) { + ??? } #[cfg(test)] @@ -49,4 +50,11 @@ mod tests { let s = String::from("Cafe au lait"); assert_eq!(char_counter(s.clone()), byte_counter(s)); } + + #[test] + fn mult_box() { + let mut num: Box<u32> = Box::new(3); + num_sq(&mut num); + assert_eq!(*num, 9); + } } diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs index 9d84174..6c272c3 100644 --- a/exercises/conversions/from_into.rs +++ b/exercises/conversions/from_into.rs @@ -1,6 +1,8 @@ // The From trait is used for value-to-value conversions. // If From is implemented correctly for a type, the Into trait should work conversely. // You can read more about it at https://doc.rust-lang.org/std/convert/trait.From.html +// Execute `rustlings hint from_into` or use the `hint` watch subcommand for a hint. + #[derive(Debug)] struct Person { name: String, diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index ece0b3c..fe16815 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -4,6 +4,8 @@ // Additionally, upon implementing FromStr, you can use the `parse` method // on strings to generate an object of the implementor type. // You can read more about it at https://doc.rust-lang.org/std/str/trait.FromStr.html +// Execute `rustlings hint from_str` or use the `hint` watch subcommand for a hint. + use std::num::ParseIntError; use std::str::FromStr; @@ -37,6 +39,9 @@ enum ParsePersonError { // with something like `"4".parse::<usize>()` // 6. If while extracting the name and the age something goes wrong, an error should be returned // If everything goes well, then return a Result of a Person object +// +// As an aside: `Box<dyn Error>` implements `From<&'_ str>`. This means that if you want to return a +// string error message, you can do so via just using return `Err("my error message".into())`. impl FromStr for Person { type Err = ParsePersonError; diff --git a/exercises/conversions/mod.rs b/exercises/conversions/mod.rs deleted file mode 100644 index 69f66ae..0000000 --- a/exercises/conversions/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod as_ref_mut; -mod from_into; -mod from_str; -mod try_from_into; -mod using_as; diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index b8ec445..fa98bc9 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -3,6 +3,8 @@ // Basically, this is the same as From. The main difference is that this should return a Result type // instead of the target type itself. // You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html +// Execute `rustlings hint try_from_into` or use the `hint` watch subcommand for a hint. + use std::convert::{TryFrom, TryInto}; #[derive(Debug, PartialEq)] @@ -54,7 +56,7 @@ impl TryFrom<&[i16]> for Color { } fn main() { - // Use the `from` function + // Use the `try_from` function let c1 = Color::try_from((183, 65, 14)); println!("{:?}", c1); diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs index f3f745f..8c9b711 100644 --- a/exercises/conversions/using_as.rs +++ b/exercises/conversions/using_as.rs @@ -4,6 +4,7 @@ // // The goal is to make sure that the division does not fail to compile // and returns the proper type. +// Execute `rustlings hint using_as` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/enums/enums1.rs b/exercises/enums/enums1.rs index a2223d3..511ba74 100644 --- a/exercises/enums/enums1.rs +++ b/exercises/enums/enums1.rs @@ -1,5 +1,5 @@ // enums1.rs -// Make me compile! Execute `rustlings hint enums1` for hints! +// No hints this time! ;) // I AM NOT DONE diff --git a/exercises/enums/enums2.rs b/exercises/enums/enums2.rs index ec32d95..18479f8 100644 --- a/exercises/enums/enums2.rs +++ b/exercises/enums/enums2.rs @@ -1,5 +1,5 @@ // enums2.rs -// Make me compile! Execute `rustlings hint enums2` for hints! +// Execute `rustlings hint enums2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs index 178b40c..55acf6b 100644 --- a/exercises/enums/enums3.rs +++ b/exercises/enums/enums3.rs @@ -1,5 +1,6 @@ // enums3.rs // Address all the TODOs to make the tests pass! +// Execute `rustlings hint enums3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/enums/mod.rs b/exercises/enums/mod.rs deleted file mode 100644 index a23fd6e..0000000 --- a/exercises/enums/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod enums1; -mod enums2; -mod enums3; diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs index c417fb2..bcee972 100644 --- a/exercises/error_handling/errors1.rs +++ b/exercises/error_handling/errors1.rs @@ -3,16 +3,16 @@ // you pass it an empty string. It'd be nicer if it explained what the problem // was, instead of just sometimes returning `None`. Thankfully, Rust has a similar // construct to `Option` that can be used to express error conditions. Let's use it! -// Execute `rustlings hint errors1` for hints! +// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE pub fn generate_nametag_text(name: String) -> Option<String> { - if name.len() > 0 { - Some(format!("Hi! My name is {}", name)) - } else { + if name.is_empty() { // Empty names aren't allowed. None + } else { + Some(format!("Hi! My name is {}", name)) } } diff --git a/exercises/error_handling/errors2.rs b/exercises/error_handling/errors2.rs index aad3a93..1cd8fc6 100644 --- a/exercises/error_handling/errors2.rs +++ b/exercises/error_handling/errors2.rs @@ -14,7 +14,8 @@ // and add. // There are at least two ways to implement this that are both correct-- but -// one is a lot shorter! Execute `rustlings hint errors2` for hints to both ways. +// one is a lot shorter! +// Execute `rustlings hint errors2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors3.rs b/exercises/error_handling/errors3.rs index 460ac5c..a2d2d19 100644 --- a/exercises/error_handling/errors3.rs +++ b/exercises/error_handling/errors3.rs @@ -2,7 +2,7 @@ // This is a program that is trying to use a completed version of the // `total_cost` function from the previous exercise. It's not working though! // Why not? What should we do to fix it? -// Execute `rustlings hint errors3` for hints! +// Execute `rustlings hint errors3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors4.rs b/exercises/error_handling/errors4.rs index 0685c37..0efe8cc 100644 --- a/exercises/error_handling/errors4.rs +++ b/exercises/error_handling/errors4.rs @@ -1,5 +1,5 @@ // errors4.rs -// Make this test pass! Execute `rustlings hint errors4` for hints :) +// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -14,6 +14,7 @@ enum CreationError { impl PositiveNonzeroInteger { fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { + // Hmm...? Why is this only returning an Ok value? Ok(PositiveNonzeroInteger(value as u64)) } } diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs index 365a869..67411c5 100644 --- a/exercises/error_handling/errors5.rs +++ b/exercises/error_handling/errors5.rs @@ -1,8 +1,18 @@ // errors5.rs -// This program uses a completed version of the code from errors4. -// It won't compile right now! Why? -// Execute `rustlings hint errors5` for hints! +// This program uses an altered version of the code from errors4. + +// This exercise uses some concepts that we won't get to until later in the course, like `Box` and the +// `From` trait. It's not important to understand them in detail right now, but you can read ahead if you like. + +// In short, this particular use case for boxes is for when you want to own a value and you care only that it is a +// type which implements a particular trait. To do so, The Box is declared as of type Box<dyn Trait> where Trait is the trait +// the compiler looks for on any value used in that context. For this exercise, that context is the potential errors +// which can be returned in a Result. + +// What can we use to describe both errors? In other words, is there a trait which both errors implement? + +// Execute `rustlings hint errors5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -11,7 +21,7 @@ use std::fmt; use std::num::ParseIntError; // TODO: update the return type of `main()` to make this compile. -fn main() -> Result<(), ParseIntError> { +fn main() -> Result<(), Box<dyn ???>> { let pretend_user_input = "42"; let x: i64 = pretend_user_input.parse()?; println!("output={:?}", PositiveNonzeroInteger::new(x)?); diff --git a/exercises/error_handling/errors6.rs b/exercises/error_handling/errors6.rs index 847a049..1306fb0 100644 --- a/exercises/error_handling/errors6.rs +++ b/exercises/error_handling/errors6.rs @@ -6,7 +6,7 @@ // we define a custom error type to make it possible for callers to decide // what to do next when our function returns an error. -// Make these tests pass! Execute `rustlings hint errors6` for hints :) +// Execute `rustlings hint errors6` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -20,7 +20,11 @@ enum ParsePosNonzeroError { } impl ParsePosNonzeroError { + fn from_creation(err: CreationError) -> ParsePosNonzeroError { + ParsePosNonzeroError::Creation(err) + } // TODO: add another error conversion function here. + // fn from_parseint... } fn parse_pos_nonzero(s: &str) diff --git a/exercises/error_handling/mod.rs b/exercises/error_handling/mod.rs deleted file mode 100644 index 539fa23..0000000 --- a/exercises/error_handling/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod errors1; -mod errors2; -mod errors3; -mod errors4; -mod errors5; -mod errors6; diff --git a/exercises/functions/README.md b/exercises/functions/README.md index 66547bd..6662d0d 100644 --- a/exercises/functions/README.md +++ b/exercises/functions/README.md @@ -1,6 +1,7 @@ # Functions -Here, you'll learn how to write functions and how Rust's compiler can trace things way back. +Here, you'll learn how to write functions and how the Rust compiler can help you debug errors even +in more complex code. ## Further information diff --git a/exercises/functions/functions1.rs b/exercises/functions/functions1.rs index 3112527..03d8af7 100644 --- a/exercises/functions/functions1.rs +++ b/exercises/functions/functions1.rs @@ -1,5 +1,5 @@ // functions1.rs -// Make me compile! Execute `rustlings hint functions1` for hints :) +// Execute `rustlings hint functions1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/functions/functions2.rs b/exercises/functions/functions2.rs index 5721a17..7d40a57 100644 --- a/exercises/functions/functions2.rs +++ b/exercises/functions/functions2.rs @@ -1,5 +1,5 @@ // functions2.rs -// Make me compile! Execute `rustlings hint functions2` for hints :) +// Execute `rustlings hint functions2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/functions/functions3.rs b/exercises/functions/functions3.rs index ed5f839..3b9e585 100644 --- a/exercises/functions/functions3.rs +++ b/exercises/functions/functions3.rs @@ -1,5 +1,5 @@ // functions3.rs -// Make me compile! Execute `rustlings hint functions3` for hints :) +// Execute `rustlings hint functions3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/functions/functions4.rs b/exercises/functions/functions4.rs index 58637e4..65d5be4 100644 --- a/exercises/functions/functions4.rs +++ b/exercises/functions/functions4.rs @@ -1,8 +1,11 @@ // functions4.rs -// Make me compile! Execute `rustlings hint functions4` for hints :) +// Execute `rustlings hint functions4` or use the `hint` watch subcommand for a hint. // This store is having a sale where if the price is an even number, you get // 10 Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. +// (Don't worry about the function bodies themselves, we're only interested +// in the signatures for now. If anything, this is a good way to peek ahead +// to future exercises!) // I AM NOT DONE diff --git a/exercises/functions/functions5.rs b/exercises/functions/functions5.rs index d22aa6c..5d76296 100644 --- a/exercises/functions/functions5.rs +++ b/exercises/functions/functions5.rs @@ -1,11 +1,11 @@ // functions5.rs -// Make me compile! Execute `rustlings hint functions5` for hints :) +// Execute `rustlings hint functions5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { let answer = square(3); - println!("The answer is {}", answer); + println!("The square of 3 is {}", answer); } fn square(num: i32) -> i32 { diff --git a/exercises/functions/mod.rs b/exercises/functions/mod.rs deleted file mode 100644 index 445b6f5..0000000 --- a/exercises/functions/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod functions1; -mod functions2; -mod functions3; -mod functions4; -mod functions5; diff --git a/exercises/generics/generics1.rs b/exercises/generics/generics1.rs index f93e64a..4c34ae4 100644 --- a/exercises/generics/generics1.rs +++ b/exercises/generics/generics1.rs @@ -1,7 +1,7 @@ // This shopping list program isn't compiling! // Use your knowledge of generics to fix it. -// Execute `rustlings hint generics1` for hints! +// Execute `rustlings hint generics1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/generics/generics2.rs b/exercises/generics/generics2.rs index 1501529..aedbd55 100644 --- a/exercises/generics/generics2.rs +++ b/exercises/generics/generics2.rs @@ -1,7 +1,7 @@ // This powerful wrapper provides the ability to store a positive integer value. // Rewrite it using generics so that it supports wrapping ANY type. -// Execute `rustlings hint generics2` for hints! +// Execute `rustlings hint generics2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/generics/generics3.rs b/exercises/generics/generics3.rs deleted file mode 100644 index 64dd9bc..0000000 --- a/exercises/generics/generics3.rs +++ /dev/null @@ -1,58 +0,0 @@ -// An imaginary magical school has a new report card generation system written in Rust! -// Currently the system only supports creating report cards where the student's grade -// is represented numerically (e.g. 1.0 -> 5.5). -// However, the school also issues alphabetical grades (A+ -> F-) and needs -// to be able to print both types of report card! - -// Make the necessary code changes in the struct ReportCard and the impl block -// to support alphabetical report cards. Change the Grade in the second test to "A+" -// to show that your changes allow alphabetical grades. - -// Execute 'rustlings hint generics3' for hints! - -// I AM NOT DONE - -pub struct ReportCard { - pub grade: f32, - pub student_name: String, - pub student_age: u8, -} - -impl ReportCard { - pub fn print(&self) -> String { - format!("{} ({}) - achieved a grade of {}", - &self.student_name, &self.student_age, &self.grade) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn generate_numeric_report_card() { - let report_card = ReportCard { - grade: 2.1, - student_name: "Tom Wriggle".to_string(), - student_age: 12, - }; - assert_eq!( - report_card.print(), - "Tom Wriggle (12) - achieved a grade of 2.1" - ); - } - - #[test] - fn generate_alphabetic_report_card() { - // TODO: Make sure to change the grade here after you finish the exercise. - let report_card = ReportCard { - grade: 2.1, - student_name: "Gary Plotter".to_string(), - student_age: 11, - }; - assert_eq!( - report_card.print(), - "Gary Plotter (11) - achieved a grade of A+" - ); - } -} diff --git a/exercises/generics/mod.rs b/exercises/generics/mod.rs deleted file mode 100644 index 5b93555..0000000 --- a/exercises/generics/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod generics1; -mod generics2; -mod generics3; diff --git a/exercises/hashmaps/README.md b/exercises/hashmaps/README.md new file mode 100644 index 0000000..30471cf --- /dev/null +++ b/exercises/hashmaps/README.md @@ -0,0 +1,11 @@ +# Hashmaps +A *hash map* allows you to associate a value with a particular key. +You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map), +[*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages. + +This is the other data structure that we've been talking about before, when +talking about Vecs. + +## Further information + +- [Storing Keys with Associated Values in Hash Maps](https://doc.rust-lang.org/book/ch08-03-hash-maps.html) diff --git a/exercises/collections/hashmap1.rs b/exercises/hashmaps/hashmaps1.rs index 64b5a7f..fd8dd2f 100644 --- a/exercises/collections/hashmap1.rs +++ b/exercises/hashmaps/hashmaps1.rs @@ -1,4 +1,4 @@ -// hashmap1.rs +// hashmaps1.rs // A basket of fruits in the form of a hash map needs to be defined. // The key represents the name of the fruit and the value represents // how many of that particular fruit is in the basket. You have to put @@ -8,8 +8,7 @@ // // Make me compile and pass the tests! // -// Execute the command `rustlings hint hashmap1` if you need -// hints. +// Execute `rustlings hint hashmaps1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/collections/hashmap2.rs b/exercises/hashmaps/hashmaps2.rs index 0abe19a..454b3e1 100644 --- a/exercises/collections/hashmap2.rs +++ b/exercises/hashmaps/hashmaps2.rs @@ -1,4 +1,4 @@ -// hashmap2.rs +// hashmaps2.rs // A basket of fruits in the form of a hash map is given. The key // represents the name of the fruit and the value represents how many @@ -9,8 +9,7 @@ // // Make me pass the tests! // -// Execute the command `rustlings hint hashmap2` if you need -// hints. +// Execute `rustlings hint hashmaps2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/hashmaps/hashmaps3.rs b/exercises/hashmaps/hashmaps3.rs new file mode 100644 index 0000000..18dd44c --- /dev/null +++ b/exercises/hashmaps/hashmaps3.rs @@ -0,0 +1,87 @@ +// hashmaps3.rs + +// A list of scores (one per line) of a soccer match is given. Each line +// is of the form : +// <team_1_name>,<team_2_name>,<team_1_goals>,<team_2_goals> +// Example: England,France,4,2 (England scored 4 goals, France 2). + +// You have to build a scores table containing the name of the team, goals +// the team scored, and goals the team conceded. One approach to build +// the scores table is to use a Hashmap. The solution is partially +// written to use a Hashmap, complete it to pass the test. + +// Make me pass the tests! + +// Execute `rustlings hint hashmaps3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +use std::collections::HashMap; + +// A structure to store team name and its goal details. +struct Team { + name: String, + goals_scored: u8, + goals_conceded: u8, +} + +fn build_scores_table(results: String) -> HashMap<String, Team> { + // The name of the team is the key and its associated struct is the value. + let mut scores: HashMap<String, Team> = HashMap::new(); + + for r in results.lines() { + let v: Vec<&str> = r.split(',').collect(); + let team_1_name = v[0].to_string(); + let team_1_score: u8 = v[2].parse().unwrap(); + let team_2_name = v[1].to_string(); + let team_2_score: u8 = v[3].parse().unwrap(); + // TODO: Populate the scores table with details extracted from the + // current line. Keep in mind that goals scored by team_1 + // will be number of goals conceded from team_2, and similarly + // goals scored by team_2 will be the number of goals conceded by + // team_1. + } + scores +} + +#[cfg(test)] +mod tests { + use super::*; + + fn get_results() -> String { + let results = "".to_string() + + "England,France,4,2\n" + + "France,Italy,3,1\n" + + "Poland,Spain,2,0\n" + + "Germany,England,2,1\n"; + results + } + + #[test] + fn build_scores() { + let scores = build_scores_table(get_results()); + + let mut keys: Vec<&String> = scores.keys().collect(); + keys.sort(); + assert_eq!( + keys, + vec!["England", "France", "Germany", "Italy", "Poland", "Spain"] + ); + } + + #[test] + fn validate_team_score_1() { + let scores = build_scores_table(get_results()); + let team = scores.get("England").unwrap(); + assert_eq!(team.goals_scored, 5); + assert_eq!(team.goals_conceded, 4); + } + + #[test] + fn validate_team_score_2() { + let scores = build_scores_table(get_results()); + let team = scores.get("Spain").unwrap(); + assert_eq!(team.goals_scored, 0); + assert_eq!(team.goals_conceded, 2); + } +} diff --git a/exercises/if/README.md b/exercises/if/README.md index 528d988..b52c392 100644 --- a/exercises/if/README.md +++ b/exercises/if/README.md @@ -1,6 +1,6 @@ # If -`if`, the most basic type of control flow, is what you'll learn here. +`if`, the most basic (but still surprisingly versatile!) type of control flow, is what you'll learn here. ## Further information diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs index 9086754..587e03f 100644 --- a/exercises/if/if1.rs +++ b/exercises/if/if1.rs @@ -1,4 +1,5 @@ // if1.rs +// Execute `rustlings hint if1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -7,7 +8,6 @@ pub fn bigger(a: i32, b: i32) -> i32 { // Do not use: // - another function call // - additional variables - // Execute `rustlings hint if1` for hints } // Don't mind this for now :) diff --git a/exercises/if/if2.rs b/exercises/if/if2.rs index 80effbd..effddbb 100644 --- a/exercises/if/if2.rs +++ b/exercises/if/if2.rs @@ -2,11 +2,11 @@ // Step 1: Make me compile! // Step 2: Get the bar_for_fuzz and default_to_baz tests passing! -// Execute the command `rustlings hint if2` if you want a hint :) +// Execute `rustlings hint if2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE -pub fn fizz_if_foo(fizzish: &str) -> &str { +pub fn foo_if_fizz(fizzish: &str) -> &str { if fizzish == "fizz" { "foo" } else { @@ -21,16 +21,16 @@ mod tests { #[test] fn foo_for_fizz() { - assert_eq!(fizz_if_foo("fizz"), "foo") + assert_eq!(foo_if_fizz("fizz"), "foo") } #[test] fn bar_for_fuzz() { - assert_eq!(fizz_if_foo("fuzz"), "bar") + assert_eq!(foo_if_fizz("fuzz"), "bar") } #[test] fn default_to_baz() { - assert_eq!(fizz_if_foo("literally anything"), "baz") + assert_eq!(foo_if_fizz("literally anything"), "baz") } } diff --git a/exercises/if/mod.rs b/exercises/if/mod.rs deleted file mode 100644 index c5d0244..0000000 --- a/exercises/if/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod if1; -mod if2; diff --git a/exercises/intro/intro1.rs b/exercises/intro/intro1.rs index 1c4582d..45c5acb 100644 --- a/exercises/intro/intro1.rs +++ b/exercises/intro/intro1.rs @@ -3,7 +3,11 @@ // We sometimes encourage you to keep trying things on a given exercise, even // after you already figured it out. If you got everything working and feel // ready for the next exercise, remove the `I AM NOT DONE` comment below. -// Execute the command `rustlings hint intro1` for a hint. +// Execute `rustlings hint intro1` or use the `hint` watch subcommand for a hint. +// +// If you're running this using `rustlings watch`: The exercise file will be reloaded +// when you change one of the lines below! Try adding a `println!` line, or try changing +// what it outputs in your terminal. Try removing a semicolon and see what happens! // I AM NOT DONE @@ -20,4 +24,7 @@ fn main() { println!("This exercise compiles successfully. The remaining exercises contain a compiler"); println!("or logic error. The central concept behind Rustlings is to fix these errors and"); println!("solve the exercises. Good luck!"); + println!(); + println!("The source for this exercise is in `exercises/intro/intro1.rs`. Have a look!"); + println!("Going forward, the source of the exercises will always be in the success/failure output."); } diff --git a/exercises/intro/intro2.rs b/exercises/intro/intro2.rs index 97a073f..efc1af2 100644 --- a/exercises/intro/intro2.rs +++ b/exercises/intro/intro2.rs @@ -1,6 +1,6 @@ // intro2.rs // Make the code print a greeting to the world. -// Execute `rustlings hint intro2` for a hint. +// Execute `rustlings hint intro2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/intro/mod.rs b/exercises/intro/mod.rs deleted file mode 100644 index 445c47a..0000000 --- a/exercises/intro/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod intro1; -mod intro2; diff --git a/exercises/lifetimes/README.md b/exercises/lifetimes/README.md new file mode 100644 index 0000000..72befb3 --- /dev/null +++ b/exercises/lifetimes/README.md @@ -0,0 +1,17 @@ +# Lifetimes + +Lifetimes tell the compiler how to check whether references live long +enough to be valid in any given situation. For example lifetimes say +"make sure parameter 'a' lives as long as parameter 'b' so that the return +value is valid". + +They are only necessary on borrows, i.e. references, +since copied parameters or moves are owned in their scope and cannot +be referenced outside. Lifetimes mean that calling code of e.g. functions +can be checked to make sure their arguments are valid. Lifetimes are +restrictive of their callers. + +## Further information + +- [Validating References with Lifetimes](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html) +- [Lifetimes (in Rust By Example)](https://doc.rust-lang.org/stable/rust-by-example/scope/lifetime.html) diff --git a/exercises/lifetimes/lifetimes1.rs b/exercises/lifetimes/lifetimes1.rs new file mode 100644 index 0000000..58e995c --- /dev/null +++ b/exercises/lifetimes/lifetimes1.rs @@ -0,0 +1,26 @@ +// lifetimes1.rs +// +// The Rust compiler needs to know how to check whether supplied references are +// valid, so that it can let the programmer know if a reference is at risk +// of going out of scope before it is used. Remember, references are borrows +// and do not own their own data. What if their owner goes out of scope? +// +// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +fn longest(x: &str, y: &str) -> &str { + if x.len() > y.len() { + x + } else { + y + } +} + +fn main() { + let string1 = String::from("abcd"); + let string2 = "xyz"; + + let result = longest(string1.as_str(), string2); + println!("The longest string is {}", result); +} diff --git a/exercises/lifetimes/lifetimes2.rs b/exercises/lifetimes/lifetimes2.rs new file mode 100644 index 0000000..c73a28a --- /dev/null +++ b/exercises/lifetimes/lifetimes2.rs @@ -0,0 +1,27 @@ +// lifetimes2.rs +// +// So if the compiler is just validating the references passed +// to the annotated parameters and the return type, what do +// we need to change? +// +// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + if x.len() > y.len() { + x + } else { + y + } +} + +fn main() { + let string1 = String::from("long string is long"); + let result; + { + let string2 = String::from("xyz"); + result = longest(string1.as_str(), string2.as_str()); + } + println!("The longest string is {}", result); +} diff --git a/exercises/lifetimes/lifetimes3.rs b/exercises/lifetimes/lifetimes3.rs new file mode 100644 index 0000000..ea48370 --- /dev/null +++ b/exercises/lifetimes/lifetimes3.rs @@ -0,0 +1,20 @@ +// lifetimes3.rs +// +// Lifetimes are also needed when structs hold references. +// +// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +struct Book { + author: &str, + title: &str, +} + +fn main() { + let name = String::from("Jill Smith"); + let title = String::from("Fish Flying"); + let book = Book { author: &name, title: &title }; + + println!("{} by {}", book.title, book.author); +} diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs index ed0dac8..634d0a7 100644 --- a/exercises/macros/macros1.rs +++ b/exercises/macros/macros1.rs @@ -1,5 +1,5 @@ // macros1.rs -// Make me compile! Execute `rustlings hint macros1` for hints :) +// Execute `rustlings hint macros1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs index d0be123..f6092ca 100644 --- a/exercises/macros/macros2.rs +++ b/exercises/macros/macros2.rs @@ -1,5 +1,5 @@ // macros2.rs -// Make me compile! Execute `rustlings hint macros2` for hints :) +// Execute `rustlings hint macros2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs index 93a4311..106f1c6 100644 --- a/exercises/macros/macros3.rs +++ b/exercises/macros/macros3.rs @@ -1,6 +1,6 @@ // macros3.rs // Make me compile, without taking the macro out of the module! -// Execute `rustlings hint macros3` for hints :) +// Execute `rustlings hint macros3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index 3a74807..c1fc5e8 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -1,5 +1,5 @@ // macros4.rs -// Make me compile! Execute `rustlings hint macros4` for hints :) +// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/macros/mod.rs b/exercises/macros/mod.rs deleted file mode 100644 index 9f65acf..0000000 --- a/exercises/macros/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod macros1; -mod macros2; -mod macros3; -mod macros4; diff --git a/exercises/mod.rs b/exercises/mod.rs deleted file mode 100644 index 6a143b5..0000000 --- a/exercises/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -mod advanced_errors; -mod clippy; -mod collections; -mod conversions; -mod enums; -mod error_handling; -mod functions; -mod generics; -mod r#if; -mod intro; -mod macros; -mod modules; -mod move_semantics; -mod option; -mod primitive_types; -mod quiz1; -mod quiz2; -mod quiz3; -mod quiz4; -mod standard_library_types; -mod strings; -mod structs; -mod tests; -mod threads; -mod traits; -mod variables; diff --git a/exercises/modules/mod.rs b/exercises/modules/mod.rs deleted file mode 100644 index 35f96af..0000000 --- a/exercises/modules/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod modules1; -mod modules2; -mod modules3; diff --git a/exercises/modules/modules1.rs b/exercises/modules/modules1.rs index 1a2bd0d..8dd0e40 100644 --- a/exercises/modules/modules1.rs +++ b/exercises/modules/modules1.rs @@ -1,5 +1,5 @@ // modules1.rs -// Make me compile! Execute `rustlings hint modules1` for hints :) +// Execute `rustlings hint modules1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs index 87f0c45..c30a389 100644 --- a/exercises/modules/modules2.rs +++ b/exercises/modules/modules2.rs @@ -1,12 +1,11 @@ // modules2.rs // You can bring module paths into scopes and provide new names for them with the // 'use' and 'as' keywords. Fix these 'use' statements to make the code compile. -// Make me compile! Execute `rustlings hint modules2` for hints :) +// Execute `rustlings hint modules2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE mod delicious_snacks { - // TODO: Fix these use statements use self::fruits::PEAR as ??? use self::veggies::CUCUMBER as ??? diff --git a/exercises/modules/modules3.rs b/exercises/modules/modules3.rs index 8eed77d..35e0799 100644 --- a/exercises/modules/modules3.rs +++ b/exercises/modules/modules3.rs @@ -3,7 +3,7 @@ // and especially from the Rust standard library into your scope. // Bring SystemTime and UNIX_EPOCH // from the std::time module. Bonus style points if you can do it with one line! -// Make me compile! Execute `rustlings hint modules3` for hints :) +// Execute `rustlings hint modules3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/mod.rs b/exercises/move_semantics/mod.rs deleted file mode 100644 index e8eecf0..0000000 --- a/exercises/move_semantics/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod move_semantics1; -mod move_semantics2; -mod move_semantics3; -mod move_semantics4; -mod move_semantics5; -mod move_semantics6; diff --git a/exercises/move_semantics/move_semantics1.rs b/exercises/move_semantics/move_semantics1.rs index e2f5876..aac6dfc 100644 --- a/exercises/move_semantics/move_semantics1.rs +++ b/exercises/move_semantics/move_semantics1.rs @@ -1,5 +1,5 @@ // move_semantics1.rs -// Make me compile! Execute `rustlings hint move_semantics1` for hints :) +// Execute `rustlings hint move_semantics1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs index 888dc52..6487085 100644 --- a/exercises/move_semantics/move_semantics2.rs +++ b/exercises/move_semantics/move_semantics2.rs @@ -1,6 +1,6 @@ // move_semantics2.rs // Make me compile without changing line 13 or moving line 10! -// Execute `rustlings hint move_semantics2` for hints :) +// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics3.rs b/exercises/move_semantics/move_semantics3.rs index 43fef74..eaa30e3 100644 --- a/exercises/move_semantics/move_semantics3.rs +++ b/exercises/move_semantics/move_semantics3.rs @@ -1,7 +1,7 @@ // move_semantics3.rs // Make me compile without adding new lines-- just changing existing lines! // (no lines with multiple semicolons necessary!) -// Execute `rustlings hint move_semantics3` for hints :) +// Execute `rustlings hint move_semantics3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics4.rs b/exercises/move_semantics/move_semantics4.rs index 2a23c71..99834ec 100644 --- a/exercises/move_semantics/move_semantics4.rs +++ b/exercises/move_semantics/move_semantics4.rs @@ -1,8 +1,8 @@ // move_semantics4.rs -// Refactor this code so that instead of having `vec0` and creating the vector -// in `fn main`, we create it within `fn fill_vec` and transfer the -// freshly created vector from fill_vec to its caller. -// Execute `rustlings hint move_semantics4` for hints! +// Refactor this code so that instead of passing `vec0` into the `fill_vec` function, +// the Vector gets created in the function itself and passed back to the main +// function. +// Execute `rustlings hint move_semantics4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics5.rs b/exercises/move_semantics/move_semantics5.rs index c4704f9..36eae12 100644 --- a/exercises/move_semantics/move_semantics5.rs +++ b/exercises/move_semantics/move_semantics5.rs @@ -1,7 +1,7 @@ // move_semantics5.rs // Make me compile only by reordering the lines in `main()`, but without // adding, changing or removing any of them. -// Execute `rustlings hint move_semantics5` for hints :) +// Execute `rustlings hint move_semantics5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics6.rs b/exercises/move_semantics/move_semantics6.rs index 457e7ae..eb52a84 100644 --- a/exercises/move_semantics/move_semantics6.rs +++ b/exercises/move_semantics/move_semantics6.rs @@ -1,6 +1,6 @@ // move_semantics6.rs -// Make me compile! `rustlings hint move_semantics6` for hints -// You can't change anything except adding or removing references +// Execute `rustlings hint move_semantics6` or use the `hint` watch subcommand for a hint. +// You can't change anything except adding or removing references. // I AM NOT DONE diff --git a/exercises/option/mod.rs b/exercises/option/mod.rs deleted file mode 100644 index b3cdb13..0000000 --- a/exercises/option/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod option1; -mod option2; -mod option3; diff --git a/exercises/option/option1.rs b/exercises/option/option1.rs deleted file mode 100644 index 17cf4f6..0000000 --- a/exercises/option/option1.rs +++ /dev/null @@ -1,23 +0,0 @@ -// option1.rs -// Make me compile! Execute `rustlings hint option1` for hints - -// I AM NOT DONE - -// you can modify anything EXCEPT for this function's signature -fn print_number(maybe_number: Option<u16>) { - println!("printing: {}", maybe_number.unwrap()); -} - -fn main() { - print_number(13); - print_number(99); - - let mut numbers: [Option<u16>; 5]; - for iter in 0..5 { - let number_to_add: u16 = { - ((iter * 1235) + 2) / (4 * 16) - }; - - numbers[iter as usize] = number_to_add; - } -} diff --git a/exercises/option/README.md b/exercises/options/README.md index 89c0028..6140a16 100644 --- a/exercises/option/README.md +++ b/exercises/options/README.md @@ -1,4 +1,4 @@ -# Option +# Options Type Option represents an optional value: every Option is either Some and contains a value, or None, and does not. Option types are very common in Rust code, as they have a number of uses: diff --git a/exercises/options/options1.rs b/exercises/options/options1.rs new file mode 100644 index 0000000..038fb48 --- /dev/null +++ b/exercises/options/options1.rs @@ -0,0 +1,37 @@ +// options1.rs +// Execute `rustlings hint options1` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +// you can modify anything EXCEPT for this function's signature +fn print_number(maybe_number: Option<u16>) { + println!("printing: {}", maybe_number.unwrap()); +} + +// This function returns how much icecream there is left in the fridge. +// If it's before 10PM, there's 5 pieces left. At 10PM, someone eats them +// all, so there'll be no more left :( +// TODO: Return an Option! +fn maybe_icecream(time_of_day: u16) -> Option<u16> { + // We use the 24-hour system here, so 10PM is a value of 22 + ??? +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn check_icecream() { + assert_eq!(maybe_icecream(10), Some(5)); + assert_eq!(maybe_icecream(23), None); + assert_eq!(maybe_icecream(22), None); + } + + #[test] + fn raw_value() { + // TODO: Fix this test. How do you get at the value contained in the Option? + let icecreams = maybe_icecream(12); + assert_eq!(icecreams, 5); + } +} diff --git a/exercises/option/option2.rs b/exercises/options/options2.rs index c6b83ec..75b66a3 100644 --- a/exercises/option/option2.rs +++ b/exercises/options/options2.rs @@ -1,5 +1,5 @@ -// option2.rs -// Make me compile! Execute `rustlings hint option2` for hints +// options2.rs +// Execute `rustlings hint options2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/option/option3.rs b/exercises/options/options3.rs index 045d2ac..3f995c5 100644 --- a/exercises/option/option3.rs +++ b/exercises/options/options3.rs @@ -1,5 +1,5 @@ -// option3.rs -// Make me compile! Execute `rustlings hint option3` for hints +// options3.rs +// Execute `rustlings hint options3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/mod.rs b/exercises/primitive_types/mod.rs deleted file mode 100644 index 2335523..0000000 --- a/exercises/primitive_types/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod primitive_types1; -mod primitive_types2; -mod primitive_types3; -mod primitive_types4; -mod primitive_types5; -mod primitive_types6; diff --git a/exercises/primitive_types/primitive_types2.rs b/exercises/primitive_types/primitive_types2.rs index 6576a4d..8730baa 100644 --- a/exercises/primitive_types/primitive_types2.rs +++ b/exercises/primitive_types/primitive_types2.rs @@ -7,6 +7,8 @@ fn main() { // Characters (`char`) + // Note the _single_ quotes, these are different from the double quotes + // you've been seeing around. let my_first_initial = 'C'; if my_first_initial.is_alphabetic() { println!("Alphabetical!"); diff --git a/exercises/primitive_types/primitive_types3.rs b/exercises/primitive_types/primitive_types3.rs index aaa518b..fa7d019 100644 --- a/exercises/primitive_types/primitive_types3.rs +++ b/exercises/primitive_types/primitive_types3.rs @@ -1,6 +1,6 @@ // primitive_types3.rs // Create an array with at least 100 elements in it where the ??? is. -// Execute `rustlings hint primitive_types3` for hints! +// Execute `rustlings hint primitive_types3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs index 10b553e..71fa243 100644 --- a/exercises/primitive_types/primitive_types4.rs +++ b/exercises/primitive_types/primitive_types4.rs @@ -1,6 +1,6 @@ // primitive_types4.rs // Get a slice out of Array a where the ??? is so that the test passes. -// Execute `rustlings hint primitive_types4` for hints!! +// Execute `rustlings hint primitive_types4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs index 680d8d2..4fd9141 100644 --- a/exercises/primitive_types/primitive_types5.rs +++ b/exercises/primitive_types/primitive_types5.rs @@ -1,6 +1,6 @@ // primitive_types5.rs // Destructure the `cat` tuple so that the println will work. -// Execute `rustlings hint primitive_types5` for hints! +// Execute `rustlings hint primitive_types5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs index b8c9b82..ddf8b42 100644 --- a/exercises/primitive_types/primitive_types6.rs +++ b/exercises/primitive_types/primitive_types6.rs @@ -1,7 +1,7 @@ // primitive_types6.rs // Use a tuple index to access the second element of `numbers`. // You can put the expression for the second element where ??? is so that the test passes. -// Execute `rustlings hint primitive_types6` for hints! +// Execute `rustlings hint primitive_types6` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/quiz1.rs b/exercises/quiz1.rs index 7bd3f58..8d05b11 100644 --- a/exercises/quiz1.rs +++ b/exercises/quiz1.rs @@ -11,14 +11,14 @@ // I AM NOT DONE // Put your function here! -// fn calculate_apple_price { +// fn calculate_price_of_apples { // Don't modify this function! #[test] fn verify_test() { - let price1 = calculate_apple_price(35); - let price2 = calculate_apple_price(40); - let price3 = calculate_apple_price(65); + let price1 = calculate_price_of_apples(35); + let price2 = calculate_price_of_apples(40); + let price3 = calculate_price_of_apples(65); assert_eq!(70, price1); assert_eq!(80, price2); diff --git a/exercises/quiz2.rs b/exercises/quiz2.rs index de0dce9..f7437fd 100644 --- a/exercises/quiz2.rs +++ b/exercises/quiz2.rs @@ -1,30 +1,62 @@ // quiz2.rs // This is a quiz for the following sections: // - Strings +// - Vecs +// - Move semantics +// - Modules +// - Enums -// Ok, here are a bunch of values-- some are `String`s, some are `&str`s. Your -// task is to call one of these two functions on each value depending on what -// you think each value is. That is, add either `string_slice` or `string` -// before the parentheses on each line. If you're right, it will compile! +// Let's build a little machine in form of a function. +// As input, we're going to give a list of strings and commands. These commands +// determine what action is going to be applied to the string. It can either be: +// - Uppercase the string +// - Trim the string +// - Append "bar" to the string a specified amount of times +// The exact form of this will be: +// - The input is going to be a Vector of a 2-length tuple, +// the first element is the string, the second one is the command. +// - The output element is going to be a Vector of strings. +// Execute `rustlings hint quiz2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE -fn string_slice(arg: &str) { - println!("{}", arg); +pub enum Command { + Uppercase, + Trim, + Append(usize), } -fn string(arg: String) { - println!("{}", arg); + +mod my_module { + use super::Command; + + // TODO: Complete the function signature! + pub fn transformer(input: ???) -> ??? { + // TODO: Complete the output declaration! + let mut output: ??? = vec![]; + for (string, command) in input.iter() { + // TODO: Complete the function body. You can do it! + } + output + } } -fn main() { - ???("blue"); - ???("red".to_string()); - ???(String::from("hi")); - ???("rust is fun!".to_owned()); - ???("nice weather".into()); - ???(format!("Interpolation {}", "Station")); - ???(&String::from("abc")[0..1]); - ???(" hello there ".trim()); - ???("Happy Monday!".to_string().replace("Mon", "Tues")); - ???("mY sHiFt KeY iS sTiCkY".to_lowercase()); +#[cfg(test)] +mod tests { + // TODO: What to we have to import to have `transformer` in scope? + use ???; + use super::Command; + + #[test] + fn it_works() { + let output = transformer(vec![ + ("hello".into(), Command::Uppercase), + (" all roads lead to rome! ".into(), Command::Trim), + ("foo".into(), Command::Append(1)), + ("bar".into(), Command::Append(5)), + ]); + assert_eq!(output[0], "HELLO"); + assert_eq!(output[1], "all roads lead to rome!"); + assert_eq!(output[2], "foobar"); + assert_eq!(output[3], "barbarbarbarbarbar"); + } } diff --git a/exercises/quiz3.rs b/exercises/quiz3.rs index fae0eed..15dc469 100644 --- a/exercises/quiz3.rs +++ b/exercises/quiz3.rs @@ -1,16 +1,32 @@ // quiz3.rs -// This is a quiz for the following sections: -// - Tests +// This quiz tests: +// - Generics +// - Traits +// An imaginary magical school has a new report card generation system written in Rust! +// Currently the system only supports creating report cards where the student's grade +// is represented numerically (e.g. 1.0 -> 5.5). +// However, the school also issues alphabetical grades (A+ -> F-) and needs +// to be able to print both types of report card! -// This quiz isn't testing our function -- make it do that in such a way that -// the test passes. Then write a second test that tests that we get the result -// we expect to get when we call `times_two` with a negative number. -// No hints, you can do this :) +// Make the necessary code changes in the struct ReportCard and the impl block +// to support alphabetical report cards. Change the Grade in the second test to "A+" +// to show that your changes allow alphabetical grades. + +// Execute `rustlings hint quiz3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE -pub fn times_two(num: i32) -> i32 { - num * 2 +pub struct ReportCard { + pub grade: f32, + pub student_name: String, + pub student_age: u8, +} + +impl ReportCard { + pub fn print(&self) -> String { + format!("{} ({}) - achieved a grade of {}", + &self.student_name, &self.student_age, &self.grade) + } } #[cfg(test)] @@ -18,13 +34,29 @@ mod tests { use super::*; #[test] - fn returns_twice_of_positive_numbers() { - assert_eq!(times_two(4), ???); + fn generate_numeric_report_card() { + let report_card = ReportCard { + grade: 2.1, + student_name: "Tom Wriggle".to_string(), + student_age: 12, + }; + assert_eq!( + report_card.print(), + "Tom Wriggle (12) - achieved a grade of 2.1" + ); } #[test] - fn returns_twice_of_negative_numbers() { - // TODO replace unimplemented!() with an assert for `times_two(-4)` - unimplemented!() + fn generate_alphabetic_report_card() { + // TODO: Make sure to change the grade here after you finish the exercise. + let report_card = ReportCard { + grade: 2.1, + student_name: "Gary Plotter".to_string(), + student_age: 11, + }; + assert_eq!( + report_card.print(), + "Gary Plotter (11) - achieved a grade of A+" + ); } } diff --git a/exercises/quiz4.rs b/exercises/quiz4.rs deleted file mode 100644 index 6c47480..0000000 --- a/exercises/quiz4.rs +++ /dev/null @@ -1,23 +0,0 @@ -// quiz4.rs -// This quiz covers the sections: -// - Modules -// - Macros - -// Write a macro that passes the quiz! No hints this time, you can do it! - -// I AM NOT DONE - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_my_macro_world() { - assert_eq!(my_macro!("world!"), "Hello world!"); - } - - #[test] - fn test_my_macro_goodbye() { - assert_eq!(my_macro!("goodbye!"), "Hello goodbye!"); - } -} diff --git a/exercises/standard_library_types/arc1.rs b/exercises/standard_library_types/arc1.rs index f60061e..93a2703 100644 --- a/exercises/standard_library_types/arc1.rs +++ b/exercises/standard_library_types/arc1.rs @@ -16,7 +16,7 @@ // Make this code compile by filling in a value for `shared_numbers` where the // first TODO comment is, and create an initial binding for `child_numbers` // where the second TODO comment is. Try not to create any copies of the `numbers` Vec! -// Execute `rustlings hint arc1` for hints :) +// Execute `rustlings hint arc1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/box1.rs b/exercises/standard_library_types/box1.rs index f312f3d..9d9237c 100644 --- a/exercises/standard_library_types/box1.rs +++ b/exercises/standard_library_types/box1.rs @@ -14,7 +14,7 @@ // // Note: the tests should not be changed // -// Execute `rustlings hint box1` for hints :) +// Execute `rustlings hint box1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators1.rs b/exercises/standard_library_types/iterators1.rs index 5aa49b6..0379c6b 100644 --- a/exercises/standard_library_types/iterators1.rs +++ b/exercises/standard_library_types/iterators1.rs @@ -6,7 +6,7 @@ // This module helps you get familiar with the structure of using an iterator and // how to go through elements within an iterable collection. // -// Execute `rustlings hint iterators1` for hints :D +// Execute `rustlings hint iterators1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators2.rs b/exercises/standard_library_types/iterators2.rs index 87b4eaa..29c53af 100644 --- a/exercises/standard_library_types/iterators2.rs +++ b/exercises/standard_library_types/iterators2.rs @@ -1,7 +1,7 @@ // iterators2.rs // In this exercise, you'll learn some of the unique advantages that iterators // can offer. Follow the steps to complete the exercise. -// As always, there are hints if you execute `rustlings hint iterators2`! +// Execute `rustlings hint iterators2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/standard_library_types/iterators3.rs index 8c66c05..c97a625 100644 --- a/exercises/standard_library_types/iterators3.rs +++ b/exercises/standard_library_types/iterators3.rs @@ -4,7 +4,7 @@ // 1. Complete the divide function to get the first four tests to pass. // 2. Get the remaining tests to pass by completing the result_with_list and // list_of_results functions. -// Execute `rustlings hint iterators3` to get some hints! +// Execute `rustlings hint iterators3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -22,7 +22,9 @@ pub struct NotDivisibleError { // Calculate `a` divided by `b` if `a` is evenly divisible by `b`. // Otherwise, return a suitable error. -pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {} +pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> { + todo!(); +} // Complete the function and return a value of the correct type so the test passes. // Desired output: Ok([1, 11, 1426, 3]) diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/standard_library_types/iterators4.rs index 8886283..a02470e 100644 --- a/exercises/standard_library_types/iterators4.rs +++ b/exercises/standard_library_types/iterators4.rs @@ -1,4 +1,5 @@ // iterators4.rs +// Execute `rustlings hint iterators4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -19,6 +20,11 @@ mod tests { use super::*; #[test] + fn factorial_of_0() { + assert_eq!(1, factorial(0)); + } + + #[test] fn factorial_of_1() { assert_eq!(1, factorial(1)); } diff --git a/exercises/standard_library_types/iterators5.rs b/exercises/standard_library_types/iterators5.rs index 93f3ae1..0593d12 100644 --- a/exercises/standard_library_types/iterators5.rs +++ b/exercises/standard_library_types/iterators5.rs @@ -6,7 +6,7 @@ // imperative style for loops. Recreate this counting functionality using // iterators. Only the two iterator methods (count_iterator and // count_collection_iterator) need to be modified. -// Execute `rustlings hint iterators5` for hints. +// Execute `rustlings hint iterators5` or use the `hint` watch subcommand for a hint. // // Make the code compile and the tests pass. @@ -34,6 +34,7 @@ fn count_for(map: &HashMap<String, Progress>, value: Progress) -> usize { fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize { // map is a hashmap with String keys and Progress values. // map = { "variables1": Complete, "from_str": None, ... } + todo!(); } fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progress) -> usize { @@ -52,6 +53,7 @@ fn count_collection_iterator(collection: &[HashMap<String, Progress>], value: Pr // collection is a slice of hashmaps. // collection = [{ "variables1": Complete, "from_str": None, ... }, // { "variables2": Complete, ... }, ... ] + todo!(); } #[cfg(test)] diff --git a/exercises/standard_library_types/mod.rs b/exercises/standard_library_types/mod.rs deleted file mode 100644 index b03acb9..0000000 --- a/exercises/standard_library_types/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod arc1; -mod box1; -mod iterators1; -mod iterators2; -mod iterators3; -mod iterators4; -mod iterators5; diff --git a/exercises/strings/mod.rs b/exercises/strings/mod.rs deleted file mode 100644 index b1b460b..0000000 --- a/exercises/strings/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod strings1; -mod strings2; diff --git a/exercises/strings/strings1.rs b/exercises/strings/strings1.rs index 8090244..0de86a1 100644 --- a/exercises/strings/strings1.rs +++ b/exercises/strings/strings1.rs @@ -1,6 +1,6 @@ // strings1.rs // Make me compile without changing the function signature! -// Execute `rustlings hint strings1` for hints ;) +// Execute `rustlings hint strings1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/strings/strings2.rs b/exercises/strings/strings2.rs index 5a2ce74..0c48ec9 100644 --- a/exercises/strings/strings2.rs +++ b/exercises/strings/strings2.rs @@ -1,6 +1,6 @@ // strings2.rs // Make me compile without changing the function signature! -// Execute `rustlings hint strings2` for hints :) +// Execute `rustlings hint strings2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/strings/strings3.rs b/exercises/strings/strings3.rs new file mode 100644 index 0000000..9e25d30 --- /dev/null +++ b/exercises/strings/strings3.rs @@ -0,0 +1,43 @@ +// strings3.rs +// Execute `rustlings hint strings3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +fn trim_me(input: &str) -> String { + // TODO: Remove whitespace from the end of a string! + ??? +} + +fn compose_me(input: &str) -> String { + // TODO: Add " world!" to the string! There's multiple ways to do this! + ??? +} + +fn replace_me(input: &str) -> String { + // TODO: Replace "cars" in the string with "balloons"! + ??? +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn trim_a_string() { + assert_eq!(trim_me("Hello! "), "Hello!"); + assert_eq!(trim_me(" What's up!"), "What's up!"); + assert_eq!(trim_me(" Hola! "), "Hola!"); + } + + #[test] + fn compose_a_string() { + assert_eq!(compose_me("Hello"), "Hello world!"); + assert_eq!(compose_me("Goodbye"), "Goodbye world!"); + } + + #[test] + fn replace_a_string() { + assert_eq!(replace_me("I think cars are cool"), "I think balloons are cool"); + assert_eq!(replace_me("I love to look at cars"), "I love to look at balloons"); + } +} diff --git a/exercises/strings/strings4.rs b/exercises/strings/strings4.rs new file mode 100644 index 0000000..c410b56 --- /dev/null +++ b/exercises/strings/strings4.rs @@ -0,0 +1,29 @@ +// strings4.rs + +// Ok, here are a bunch of values-- some are `String`s, some are `&str`s. Your +// task is to call one of these two functions on each value depending on what +// you think each value is. That is, add either `string_slice` or `string` +// before the parentheses on each line. If you're right, it will compile! +// No hints this time! + +// I AM NOT DONE + +fn string_slice(arg: &str) { + println!("{}", arg); +} +fn string(arg: String) { + println!("{}", arg); +} + +fn main() { + ???("blue"); + ???("red".to_string()); + ???(String::from("hi")); + ???("rust is fun!".to_owned()); + ???("nice weather".into()); + ???(format!("Interpolation {}", "Station")); + ???(&String::from("abc")[0..1]); + ???(" hello there ".trim()); + ???("Happy Monday!".to_string().replace("Mon", "Tues")); + ???("mY sHiFt KeY iS sTiCkY".to_lowercase()); +} diff --git a/exercises/structs/mod.rs b/exercises/structs/mod.rs deleted file mode 100644 index 214fed1..0000000 --- a/exercises/structs/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod structs1; -mod structs2; -mod structs3; diff --git a/exercises/structs/structs1.rs b/exercises/structs/structs1.rs index 6d0b2f4..0d91c46 100644 --- a/exercises/structs/structs1.rs +++ b/exercises/structs/structs1.rs @@ -1,5 +1,6 @@ // structs1.rs // Address all the TODOs to make the tests pass! +// Execute `rustlings hint structs1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -10,7 +11,7 @@ struct ColorClassicStruct { struct ColorTupleStruct(/* TODO: Something goes here */); #[derive(Debug)] -struct UnitStruct; +struct UnitLikeStruct; #[cfg(test)] mod tests { @@ -21,8 +22,9 @@ mod tests { // TODO: Instantiate a classic c struct! // let green = - assert_eq!(green.name, "green"); - assert_eq!(green.hex, "#00FF00"); + assert_eq!(green.red, 0); + assert_eq!(green.green, 255); + assert_eq!(green.blue, 0); } #[test] @@ -30,16 +32,17 @@ mod tests { // TODO: Instantiate a tuple struct! // let green = - assert_eq!(green.0, "green"); - assert_eq!(green.1, "#00FF00"); + assert_eq!(green.0, 0); + assert_eq!(green.1, 255); + assert_eq!(green.2, 0); } #[test] fn unit_structs() { - // TODO: Instantiate a unit struct! - // let unit_struct = - let message = format!("{:?}s are fun!", unit_struct); + // TODO: Instantiate a unit-like struct! + // let unit_like_struct = + let message = format!("{:?}s are fun!", unit_like_struct); - assert_eq!(message, "UnitStructs are fun!"); + assert_eq!(message, "UnitLikeStructs are fun!"); } } diff --git a/exercises/structs/structs2.rs b/exercises/structs/structs2.rs index f9c6427..32e311f 100644 --- a/exercises/structs/structs2.rs +++ b/exercises/structs/structs2.rs @@ -1,5 +1,6 @@ // structs2.rs // Address all the TODOs to make the tests pass! +// Execute `rustlings hint structs2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/structs/structs3.rs b/exercises/structs/structs3.rs index e84f2eb..0b3615f 100644 --- a/exercises/structs/structs3.rs +++ b/exercises/structs/structs3.rs @@ -2,7 +2,7 @@ // Structs contain data, but can also have logic. In this exercise we have // defined the Package struct and we want to test some logic attached to it. // Make the code compile and the tests pass! -// If you have issues execute `rustlings hint structs3` +// Execute `rustlings hint structs3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -16,7 +16,7 @@ struct Package { impl Package { fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package { if weight_in_grams <= 0 { - // panic statement goes here... + panic!("Can not ship a weightless package.") } else { Package { sender_country, diff --git a/exercises/tests/mod.rs b/exercises/tests/mod.rs deleted file mode 100644 index 489541b..0000000 --- a/exercises/tests/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod tests1; -mod tests2; -mod tests3; diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs index 50586a1..8b6ea37 100644 --- a/exercises/tests/tests1.rs +++ b/exercises/tests/tests1.rs @@ -4,7 +4,8 @@ // rustlings run tests1 // This test has a problem with it -- make the test compile! Make the test -// pass! Make the test fail! Execute `rustlings hint tests1` for hints :) +// pass! Make the test fail! +// Execute `rustlings hint tests1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/tests/tests2.rs b/exercises/tests/tests2.rs index 0d981ad..a5ac15b 100644 --- a/exercises/tests/tests2.rs +++ b/exercises/tests/tests2.rs @@ -1,6 +1,7 @@ // tests2.rs // This test has a problem with it -- make the test compile! Make the test -// pass! Make the test fail! Execute `rustlings hint tests2` for hints :) +// pass! Make the test fail! +// Execute `rustlings hint tests2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs index 3424f94..196a81a 100644 --- a/exercises/tests/tests3.rs +++ b/exercises/tests/tests3.rs @@ -2,7 +2,7 @@ // This test isn't testing our function -- make it do that in such a way that // the test passes. Then write a second test that tests whether we get the result // we expect to get when we call `is_even(5)`. -// Execute `rustlings hint tests3` for hints :) +// Execute `rustlings hint tests3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/threads/mod.rs b/exercises/threads/mod.rs deleted file mode 100644 index 24d5400..0000000 --- a/exercises/threads/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod threads1; diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index f31b317..e59f4ce 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -1,32 +1,31 @@ // threads1.rs -// Make this compile! Execute `rustlings hint threads1` for hints :) -// The idea is the thread spawned on line 22 is completing jobs while the main thread is -// monitoring progress until 10 jobs are completed. Because of the difference between the -// spawned threads' sleep time, and the waiting threads sleep time, when you see 6 lines -// of "waiting..." and the program ends without timing out when running, -// you've got it :) +// Execute `rustlings hint threads1` or use the `hint` watch subcommand for a hint. +// This program should wait until all the spawned threads have finished before exiting. // I AM NOT DONE -use std::sync::Arc; use std::thread; use std::time::Duration; -struct JobStatus { - jobs_completed: u32, -} fn main() { - let status = Arc::new(JobStatus { jobs_completed: 0 }); - let status_shared = status.clone(); - thread::spawn(move || { - for _ in 0..10 { + + let mut handles = vec![]; + for i in 0..10 { + thread::spawn(move || { thread::sleep(Duration::from_millis(250)); - status_shared.jobs_completed += 1; - } - }); - while status.jobs_completed < 10 { - println!("waiting... "); - thread::sleep(Duration::from_millis(500)); + println!("thread {} is complete", i); + }); + } + + let mut completed_threads = 0; + for handle in handles { + // TODO: a struct is returned from thread::spawn, can you use it? + completed_threads += 1; + } + + if completed_threads != 10 { + panic!("Oh no! All the spawned threads did not finish!"); } + } diff --git a/exercises/threads/threads2.rs b/exercises/threads/threads2.rs new file mode 100644 index 0000000..d0f8578 --- /dev/null +++ b/exercises/threads/threads2.rs @@ -0,0 +1,34 @@ +// threads2.rs +// Execute `rustlings hint threads2` or use the `hint` watch subcommand for a hint. +// Building on the last exercise, we want all of the threads to complete their work but this time +// the spawned threads need to be in charge of updating a shared value: JobStatus.jobs_completed + +// I AM NOT DONE + +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +struct JobStatus { + jobs_completed: u32, +} + +fn main() { + let status = Arc::new(JobStatus { jobs_completed: 0 }); + let mut handles = vec![]; + for _ in 0..10 { + let status_shared = status.clone(); + 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_completed += 1; + }); + handles.push(handle); + } + for handle in handles { + handle.join().unwrap(); + // TODO: Print the value of the JobStatus.jobs_completed. Did you notice anything + // interesting in the output? Do you have to 'join' on all the handles? + println!("jobs completed {}", ???); + } +} diff --git a/exercises/threads/threads3.rs b/exercises/threads/threads3.rs new file mode 100644 index 0000000..27e9908 --- /dev/null +++ b/exercises/threads/threads3.rs @@ -0,0 +1,64 @@ +// threads3.rs +// Execute `rustlings hint threads3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +use std::sync::mpsc; +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +struct Queue { + length: u32, + first_half: Vec<u32>, + second_half: Vec<u32>, +} + +impl Queue { + fn new() -> Self { + Queue { + length: 10, + first_half: vec![1, 2, 3, 4, 5], + second_half: vec![6, 7, 8, 9, 10], + } + } +} + +fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () { + let qc = Arc::new(q); + let qc1 = qc.clone(); + let qc2 = qc.clone(); + + thread::spawn(move || { + for val in &qc1.first_half { + println!("sending {:?}", val); + tx.send(*val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); + + thread::spawn(move || { + for val in &qc2.second_half { + println!("sending {:?}", val); + tx.send(*val).unwrap(); + thread::sleep(Duration::from_secs(1)); + } + }); +} + +fn main() { + let (tx, rx) = mpsc::channel(); + let queue = Queue::new(); + let queue_length = queue.length; + + send_tx(queue, tx); + + let mut total_received: u32 = 0; + for received in rx { + println!("Got: {}", received); + total_received += 1; + } + + println!("total numbers received: {}", total_received); + assert_eq!(total_received, queue_length) +} diff --git a/exercises/traits/mod.rs b/exercises/traits/mod.rs deleted file mode 100644 index 6f0a9c3..0000000 --- a/exercises/traits/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod traits1; -mod traits2; diff --git a/exercises/traits/traits1.rs b/exercises/traits/traits1.rs index 15e08f2..5b9d8d5 100644 --- a/exercises/traits/traits1.rs +++ b/exercises/traits/traits1.rs @@ -7,6 +7,7 @@ // The trait AppendBar has only one function, // which appends "Bar" to any object // implementing this trait. +// Execute `rustlings hint traits1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/traits/traits2.rs b/exercises/traits/traits2.rs index 916c3c4..708bb19 100644 --- a/exercises/traits/traits2.rs +++ b/exercises/traits/traits2.rs @@ -9,6 +9,7 @@ // // No boiler plate code this time, // you can do this! +// Execute `rustlings hint traits2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/traits/traits3.rs b/exercises/traits/traits3.rs new file mode 100644 index 0000000..6d2fd6c --- /dev/null +++ b/exercises/traits/traits3.rs @@ -0,0 +1,41 @@ +// traits3.rs +// +// Your task is to implement the Licensed trait for +// both structures and have them return the same +// information without writing the same function twice. +// +// Consider what you can add to the Licensed trait. +// Execute `rustlings hint traits3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +pub trait Licensed { + fn licensing_info(&self) -> String; +} + +struct SomeSoftware { + version_number: i32, +} + +struct OtherSoftware { + version_number: String, +} + +impl Licensed for SomeSoftware {} // Don't edit this line +impl Licensed for OtherSoftware {} // Don't edit this line + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn is_licensing_info_the_same() { + let licensing_info = String::from("Some information"); + 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/traits/traits4.rs b/exercises/traits/traits4.rs new file mode 100644 index 0000000..280aaad --- /dev/null +++ b/exercises/traits/traits4.rs @@ -0,0 +1,45 @@ +// traits4.rs +// +// Your task is to replace the '??' sections so the code compiles. +// Don't change any line other than 21. +// Execute `rustlings hint traits4` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +pub trait Licensed { + fn licensing_info(&self) -> String { + "some information".to_string() + } +} + +struct SomeSoftware {} + +struct OtherSoftware {} + +impl Licensed for SomeSoftware {} +impl Licensed for OtherSoftware {} + +fn compare_license_types(software: ??, software_two: ??) -> bool { + software.licensing_info() == software_two.licensing_info() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn compare_license_information() { + let some_software = SomeSoftware {}; + let other_software = OtherSoftware {}; + + assert!(compare_license_types(some_software, other_software)); + } + + #[test] + fn compare_license_information_backwards() { + let some_software = SomeSoftware {}; + let other_software = OtherSoftware {}; + + assert!(compare_license_types(other_software, some_software)); + } +} diff --git a/exercises/traits/traits5.rs b/exercises/traits/traits5.rs new file mode 100644 index 0000000..290c047 --- /dev/null +++ b/exercises/traits/traits5.rs @@ -0,0 +1,32 @@ +// traits5.rs +// +// Your task is to replace the '??' sections so the code compiles. +// Don't change any line other than 27. +// Execute `rustlings hint traits5` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +pub trait SomeTrait { + fn some_function(&self) -> bool { + true + } +} + +pub trait OtherTrait { + fn other_function(&self) -> bool { + true + } +} + +struct SomeStruct { + name: String, +} + +impl SomeTrait for SomeStruct {} +impl OtherTrait for SomeStruct {} + +fn some_func(item: ??) -> bool { + item.some_function() && item.other_function() +} + +fn main() {} diff --git a/exercises/variables/mod.rs b/exercises/variables/mod.rs deleted file mode 100644 index a25f477..0000000 --- a/exercises/variables/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod variables1; -mod variables2; -mod variables3; -mod variables4; -mod variables5; -mod variables6; diff --git a/exercises/variables/variables1.rs b/exercises/variables/variables1.rs index d1af831..f4d182a 100644 --- a/exercises/variables/variables1.rs +++ b/exercises/variables/variables1.rs @@ -1,6 +1,6 @@ // variables1.rs // Make me compile! -// Execute the command `rustlings hint variables1` if you want a hint :) +// Execute `rustlings hint variables1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/variables/variables2.rs b/exercises/variables/variables2.rs index 7774a8f..641aeb8 100644 --- a/exercises/variables/variables2.rs +++ b/exercises/variables/variables2.rs @@ -1,13 +1,13 @@ // variables2.rs -// Make me compile! Execute the command `rustlings hint variables2` if you want a hint :) +// Execute `rustlings hint variables2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { let x; if x == 10 { - println!("Ten!"); + println!("x is ten!"); } else { - println!("Not ten!"); + println!("x is not ten!"); } } diff --git a/exercises/variables/variables3.rs b/exercises/variables/variables3.rs index 30ec48f..819b1bc 100644 --- a/exercises/variables/variables3.rs +++ b/exercises/variables/variables3.rs @@ -1,11 +1,9 @@ // variables3.rs -// Make me compile! Execute the command `rustlings hint variables3` if you want a hint :) +// Execute `rustlings hint variables3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { - let x = 3; - println!("Number {}", x); - x = 5; // don't change this line + let x: i32; println!("Number {}", x); } diff --git a/exercises/variables/variables4.rs b/exercises/variables/variables4.rs index 77f1e9a..54491b0 100644 --- a/exercises/variables/variables4.rs +++ b/exercises/variables/variables4.rs @@ -1,9 +1,11 @@ // variables4.rs -// Make me compile! Execute the command `rustlings hint variables4` if you want a hint :) +// Execute `rustlings hint variables4` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { - let x: i32; + let x = 3; + println!("Number {}", x); + x = 5; // don't change this line println!("Number {}", x); } diff --git a/exercises/variables/variables5.rs b/exercises/variables/variables5.rs index 175eebb..0e670d2 100644 --- a/exercises/variables/variables5.rs +++ b/exercises/variables/variables5.rs @@ -1,11 +1,11 @@ // variables5.rs -// Make me compile! Execute the command `rustlings hint variables5` if you want a hint :) +// Execute `rustlings hint variables5` or use the `hint` watch subcommand for a hint. // I AM NOT DONE fn main() { let number = "T-H-R-E-E"; // don't change this line println!("Spell a Number : {}", number); - number = 3; + number = 3; // don't rename this variable println!("Number plus two is : {}", number + 2); } diff --git a/exercises/variables/variables6.rs b/exercises/variables/variables6.rs index 9866691..a852012 100644 --- a/exercises/variables/variables6.rs +++ b/exercises/variables/variables6.rs @@ -1,5 +1,5 @@ // variables6.rs -// Make me compile! Execute the command `rustlings hint variables6` if you want a hint :) +// Execute `rustlings hint variables6` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/vecs/README.md b/exercises/vecs/README.md new file mode 100644 index 0000000..ebe90bf --- /dev/null +++ b/exercises/vecs/README.md @@ -0,0 +1,15 @@ +# Vectors + +Vectors are one of the most-used Rust data structures. In other programming +languages, they'd simply be called Arrays, but since Rust operates on a +bit of a lower level, an array in Rust is stored on the stack (meaning it +can't grow or shrink, and the size needs to be known at compile time), +and a Vector is stored in the heap (where these restrictions do not apply). + +Vectors are a bit of a later chapter in the book, but we think that they're +useful enough to talk about them a bit earlier. We shall be talking about +the other useful data structure, hash maps, later. + +## Further information + +- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html) diff --git a/exercises/collections/vec1.rs b/exercises/vecs/vecs1.rs index b144fb9..4e8c4cb 100644 --- a/exercises/collections/vec1.rs +++ b/exercises/vecs/vecs1.rs @@ -1,8 +1,8 @@ -// vec1.rs +// vecs1.rs // Your task is to create a `Vec` which holds the exact same elements // as in the array `a`. // Make me compile and pass the test! -// Execute the command `rustlings hint vec1` if you need hints. +// Execute `rustlings hint vecs1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/collections/vec2.rs b/exercises/vecs/vecs2.rs index 6595e40..5bea09a 100644 --- a/exercises/collections/vec2.rs +++ b/exercises/vecs/vecs2.rs @@ -1,11 +1,10 @@ -// vec2.rs +// vecs2.rs // A Vec of even numbers is given. Your task is to complete the loop // so that each number in the Vec is multiplied by 2. // // Make me pass the test! // -// Execute the command `rustlings hint vec2` if you need -// hints. +// Execute `rustlings hint vecs2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -13,12 +12,21 @@ fn vec_loop(mut v: Vec<i32>) -> Vec<i32> { for i in v.iter_mut() { // TODO: Fill this up so that each element in the Vec `v` is // multiplied by 2. + ??? } // At this point, `v` should be equal to [4, 8, 12, 16, 20]. v } +fn vec_map(v: &Vec<i32>) -> Vec<i32> { + v.iter().map(|num| { + // TODO: Do the same thing as above - but instead of mutating the + // Vec, you can just return the new number! + ??? + }).collect() +} + #[cfg(test)] mod tests { use super::*; @@ -30,4 +38,12 @@ mod tests { assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>()); } + + #[test] + fn test_vec_map() { + let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect(); + let ans = vec_map(&v); + + assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>()); + } } |
