summaryrefslogtreecommitdiff
path: root/exercises
diff options
context:
space:
mode:
authormokou <mokou@fastmail.com>2022-07-15 14:31:49 +0200
committermokou <mokou@fastmail.com>2022-07-15 14:31:49 +0200
commitc791cf4232fbfc313279b19b483c1adbca1c6862 (patch)
tree655ad6c9d33dab11dfd70f28d0ec29d03749a70b /exercises
parentf1c4caa37fe5027d121aec6433dee85433d9329d (diff)
parentc265b681b188ea21b3f8585e65ea363fc02c4b50 (diff)
Merge branch '5.0-dev'
Diffstat (limited to 'exercises')
-rw-r--r--exercises/advanced_errors/advanced_errs1.rs98
-rw-r--r--exercises/advanced_errors/advanced_errs2.rs202
-rw-r--r--exercises/advanced_errors/mod.rs2
-rw-r--r--exercises/clippy/clippy1.rs2
-rw-r--r--exercises/clippy/clippy2.rs2
-rw-r--r--exercises/clippy/clippy3.rs28
-rw-r--r--exercises/clippy/mod.rs2
-rw-r--r--exercises/collections/README.md23
-rw-r--r--exercises/collections/mod.rs4
-rw-r--r--exercises/conversions/as_ref_mut.rs16
-rw-r--r--exercises/conversions/from_into.rs2
-rw-r--r--exercises/conversions/from_str.rs5
-rw-r--r--exercises/conversions/mod.rs5
-rw-r--r--exercises/conversions/try_from_into.rs4
-rw-r--r--exercises/conversions/using_as.rs1
-rw-r--r--exercises/enums/enums1.rs2
-rw-r--r--exercises/enums/enums2.rs2
-rw-r--r--exercises/enums/enums3.rs1
-rw-r--r--exercises/enums/mod.rs3
-rw-r--r--exercises/error_handling/errors1.rs8
-rw-r--r--exercises/error_handling/errors2.rs3
-rw-r--r--exercises/error_handling/errors3.rs2
-rw-r--r--exercises/error_handling/errors4.rs3
-rw-r--r--exercises/error_handling/errors5.rs18
-rw-r--r--exercises/error_handling/errors6.rs6
-rw-r--r--exercises/error_handling/mod.rs6
-rw-r--r--exercises/functions/README.md3
-rw-r--r--exercises/functions/functions1.rs2
-rw-r--r--exercises/functions/functions2.rs2
-rw-r--r--exercises/functions/functions3.rs2
-rw-r--r--exercises/functions/functions4.rs5
-rw-r--r--exercises/functions/functions5.rs4
-rw-r--r--exercises/functions/mod.rs5
-rw-r--r--exercises/generics/generics1.rs2
-rw-r--r--exercises/generics/generics2.rs2
-rw-r--r--exercises/generics/generics3.rs58
-rw-r--r--exercises/generics/mod.rs3
-rw-r--r--exercises/hashmaps/README.md11
-rw-r--r--exercises/hashmaps/hashmaps1.rs (renamed from exercises/collections/hashmap1.rs)5
-rw-r--r--exercises/hashmaps/hashmaps2.rs (renamed from exercises/collections/hashmap2.rs)5
-rw-r--r--exercises/hashmaps/hashmaps3.rs87
-rw-r--r--exercises/if/README.md2
-rw-r--r--exercises/if/if1.rs2
-rw-r--r--exercises/if/if2.rs10
-rw-r--r--exercises/if/mod.rs2
-rw-r--r--exercises/intro/intro1.rs9
-rw-r--r--exercises/intro/intro2.rs2
-rw-r--r--exercises/intro/mod.rs2
-rw-r--r--exercises/lifetimes/README.md17
-rw-r--r--exercises/lifetimes/lifetimes1.rs26
-rw-r--r--exercises/lifetimes/lifetimes2.rs27
-rw-r--r--exercises/lifetimes/lifetimes3.rs20
-rw-r--r--exercises/macros/macros1.rs2
-rw-r--r--exercises/macros/macros2.rs2
-rw-r--r--exercises/macros/macros3.rs2
-rw-r--r--exercises/macros/macros4.rs2
-rw-r--r--exercises/macros/mod.rs4
-rw-r--r--exercises/mod.rs26
-rw-r--r--exercises/modules/mod.rs3
-rw-r--r--exercises/modules/modules1.rs2
-rw-r--r--exercises/modules/modules2.rs3
-rw-r--r--exercises/modules/modules3.rs2
-rw-r--r--exercises/move_semantics/mod.rs6
-rw-r--r--exercises/move_semantics/move_semantics1.rs2
-rw-r--r--exercises/move_semantics/move_semantics2.rs2
-rw-r--r--exercises/move_semantics/move_semantics3.rs2
-rw-r--r--exercises/move_semantics/move_semantics4.rs8
-rw-r--r--exercises/move_semantics/move_semantics5.rs2
-rw-r--r--exercises/move_semantics/move_semantics6.rs4
-rw-r--r--exercises/option/mod.rs3
-rw-r--r--exercises/option/option1.rs23
-rw-r--r--exercises/options/README.md (renamed from exercises/option/README.md)2
-rw-r--r--exercises/options/options1.rs37
-rw-r--r--exercises/options/options2.rs (renamed from exercises/option/option2.rs)4
-rw-r--r--exercises/options/options3.rs (renamed from exercises/option/option3.rs)4
-rw-r--r--exercises/primitive_types/mod.rs6
-rw-r--r--exercises/primitive_types/primitive_types2.rs2
-rw-r--r--exercises/primitive_types/primitive_types3.rs2
-rw-r--r--exercises/primitive_types/primitive_types4.rs2
-rw-r--r--exercises/primitive_types/primitive_types5.rs2
-rw-r--r--exercises/primitive_types/primitive_types6.rs2
-rw-r--r--exercises/quiz1.rs8
-rw-r--r--exercises/quiz2.rs70
-rw-r--r--exercises/quiz3.rs58
-rw-r--r--exercises/quiz4.rs23
-rw-r--r--exercises/standard_library_types/arc1.rs2
-rw-r--r--exercises/standard_library_types/box1.rs2
-rw-r--r--exercises/standard_library_types/iterators1.rs2
-rw-r--r--exercises/standard_library_types/iterators2.rs2
-rw-r--r--exercises/standard_library_types/iterators3.rs6
-rw-r--r--exercises/standard_library_types/iterators4.rs6
-rw-r--r--exercises/standard_library_types/iterators5.rs4
-rw-r--r--exercises/standard_library_types/mod.rs7
-rw-r--r--exercises/strings/mod.rs2
-rw-r--r--exercises/strings/strings1.rs2
-rw-r--r--exercises/strings/strings2.rs2
-rw-r--r--exercises/strings/strings3.rs43
-rw-r--r--exercises/strings/strings4.rs29
-rw-r--r--exercises/structs/mod.rs3
-rw-r--r--exercises/structs/structs1.rs21
-rw-r--r--exercises/structs/structs2.rs1
-rw-r--r--exercises/structs/structs3.rs4
-rw-r--r--exercises/tests/mod.rs3
-rw-r--r--exercises/tests/tests1.rs3
-rw-r--r--exercises/tests/tests2.rs3
-rw-r--r--exercises/tests/tests3.rs2
-rw-r--r--exercises/threads/mod.rs1
-rw-r--r--exercises/threads/threads1.rs39
-rw-r--r--exercises/threads/threads2.rs34
-rw-r--r--exercises/threads/threads3.rs64
-rw-r--r--exercises/traits/mod.rs2
-rw-r--r--exercises/traits/traits1.rs1
-rw-r--r--exercises/traits/traits2.rs1
-rw-r--r--exercises/traits/traits3.rs41
-rw-r--r--exercises/traits/traits4.rs45
-rw-r--r--exercises/traits/traits5.rs32
-rw-r--r--exercises/variables/mod.rs6
-rw-r--r--exercises/variables/variables1.rs2
-rw-r--r--exercises/variables/variables2.rs6
-rw-r--r--exercises/variables/variables3.rs6
-rw-r--r--exercises/variables/variables4.rs6
-rw-r--r--exercises/variables/variables5.rs4
-rw-r--r--exercises/variables/variables6.rs2
-rw-r--r--exercises/vecs/README.md15
-rw-r--r--exercises/vecs/vecs1.rs (renamed from exercises/collections/vec1.rs)4
-rw-r--r--exercises/vecs/vecs2.rs (renamed from exercises/collections/vec2.rs)22
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>>());
+ }
}