From 9d46b94f9fb0653decf3cf22a9bdffbb2ae3896f Mon Sep 17 00:00:00 2001
From: Yuhua Mai <yuhua@urbandoor.com>
Date: Sat, 16 May 2020 11:52:56 -0700
Subject: [PATCH] Finish exercises

---
 exercises/conversions/as_ref_mut.rs           |  5 ++-
 exercises/conversions/from_into.rs            | 17 ++++++++-
 exercises/conversions/from_str.rs             | 15 ++++++--
 exercises/conversions/try_from_into.rs        | 17 +++++++--
 exercises/conversions/using_as.rs             |  9 ++---
 exercises/generics/generics1.rs               |  3 +-
 exercises/generics/generics2.rs               | 17 ++++-----
 exercises/generics/generics3.rs               | 35 ++++++++++++-------
 exercises/standard_library_types/arc1.rs      |  7 ++--
 .../standard_library_types/iterators2.rs      | 11 +++---
 .../standard_library_types/iterators3.rs      | 24 +++++++++----
 .../standard_library_types/iterators4.rs      |  6 +++-
 exercises/threads/threads1.rs                 | 19 +++++-----
 exercises/traits/traits1.rs                   |  7 ++--
 exercises/traits/traits2.rs                   | 18 +++++-----
 15 files changed, 134 insertions(+), 76 deletions(-)

diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs
index aa1e623..c9d50c5 100644
--- a/exercises/conversions/as_ref_mut.rs
+++ b/exercises/conversions/as_ref_mut.rs
@@ -2,16 +2,15 @@
 // 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.
 
-// I AM NOT DONE
 // Obtain the number of bytes (not characters) in the given argument
 // Add the AsRef trait appropriately as a trait bound
-fn byte_counter<T>(arg: T) -> usize {
+fn byte_counter<T: AsRef<str>>(arg: T) -> usize {
     arg.as_ref().as_bytes().len()
 }
 
 // Obtain the number of characters (not bytes) in the given argument
 // Add the AsRef trait appropriately as a trait bound
-fn char_counter<T>(arg: T) -> usize {
+fn char_counter<T: AsRef<str> >(arg: T) -> usize {
     arg.as_ref().chars().count()
 }
 
diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs
index 58b860e..19053ff 100644
--- a/exercises/conversions/from_into.rs
+++ b/exercises/conversions/from_into.rs
@@ -18,7 +18,6 @@ impl Default for Person {
     }
 }
 
-// I AM NOT DONE
 // Your task is to complete this implementation
 // in order for the line `let p = Person::from("Mark,20")` to compile
 // Please note that you'll need to parse the age component into a `usize`
@@ -34,6 +33,18 @@ impl Default for Person {
 // Otherwise, then return an instantiated Person onject with the results
 impl From<&str> for Person {
     fn from(s: &str) -> Person {
+        if s.is_empty() {
+            return Default::default();
+        }
+
+        let splits: Vec<&str> = s.split(",").collect::<Vec<&str>>();
+        let name = splits[0].to_string();
+        let age_result = splits[1].parse::<usize>();
+
+        match age_result {
+            Ok(age) => Person { name, age },
+            Error => Default::default(),
+        }
     }
 }
 
@@ -49,6 +60,7 @@ fn main() {
 #[cfg(test)]
 mod tests {
     use super::*;
+
     #[test]
     fn test_default() {
         // Test that the default person is 30 year old John
@@ -56,6 +68,7 @@ mod tests {
         assert_eq!(dp.name, "John");
         assert_eq!(dp.age, 30);
     }
+
     #[test]
     fn test_bad_convert() {
         // Test that John is returned when bad string is provided
@@ -63,6 +76,7 @@ mod tests {
         assert_eq!(p.name, "John");
         assert_eq!(p.age, 30);
     }
+
     #[test]
     fn test_good_convert() {
         // Test that "Mark,20" works
@@ -70,6 +84,7 @@ mod tests {
         assert_eq!(p.name, "Mark");
         assert_eq!(p.age, 20);
     }
+
     #[test]
     fn test_bad_age() {
         // Test that "Mark.twenty" will return the default person due to an error in parsing age
diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs
index 3c889d7..57beff9 100644
--- a/exercises/conversions/from_str.rs
+++ b/exercises/conversions/from_str.rs
@@ -10,7 +10,6 @@ struct Person {
     age: usize,
 }
 
-// I AM NOT DONE
 // Steps:
 // 1. If the length of the provided string is 0, then return an error
 // 2. Split the given string on the commas present in it
@@ -21,6 +20,18 @@ struct Person {
 impl FromStr for Person {
     type Err = String;
     fn from_str(s: &str) -> Result<Person, Self::Err> {
+        if s.is_empty() {
+            return Err("empty &str".to_string());
+        }
+
+        let splits: Vec<&str> = s.split(",").collect::<Vec<&str>>();
+        let name = splits[0].to_string();
+        let age_result = splits[1].parse::<usize>();
+
+        match age_result {
+            Ok(age) => Ok(Person { name, age }),
+            Error => Err("incorrect age".to_string()),
+        }
     }
 }
 
@@ -46,4 +57,4 @@ mod tests {
     fn missing_age() {
         "John".parse::<Person>().unwrap();
     }
-}
\ No newline at end of file
+}
diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs
index 255d2e1..82fda30 100644
--- a/exercises/conversions/try_from_into.rs
+++ b/exercises/conversions/try_from_into.rs
@@ -2,7 +2,7 @@
 // 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
-use std::convert::{TryInto, TryFrom};
+use std::convert::{TryFrom, TryInto};
 
 #[derive(Debug)]
 struct Person {
@@ -10,7 +10,6 @@ struct Person {
     age: usize,
 }
 
-// I AM NOT DONE
 // Your task is to complete this implementation
 // in order for the line `let p = Person::try_from("Mark,20")` to compile
 // and return an Ok result of inner type Person.
@@ -28,6 +27,18 @@ struct Person {
 impl TryFrom<&str> for Person {
     type Error = String;
     fn try_from(s: &str) -> Result<Self, Self::Error> {
+        if s.is_empty() {
+            return Err("empty &str".to_string());
+        }
+
+        let splits: Vec<&str> = s.split(",").collect::<Vec<&str>>();
+        let name = splits[0].to_string();
+        let age_result = splits[1].parse::<usize>();
+
+        match age_result {
+            Ok(age) => Ok(Person { name, age }),
+            Error => Err("incorrect age".to_string()),
+        }
     }
 }
 
@@ -68,4 +79,4 @@ mod tests {
     fn test_panic_bad_age() {
         let p = Person::try_from("Mark,twenty").unwrap();
     }
-}
\ No newline at end of file
+}
diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs
index 54f9651..8e8264f 100644
--- a/exercises/conversions/using_as.rs
+++ b/exercises/conversions/using_as.rs
@@ -2,16 +2,13 @@
 // Please note that the `as` operator is not only used when type casting.
 // It also helps with renaming imports.
 
-// I AM NOT DONE
 // The goal is to make sure that the division does not fail to compile
 fn average(values: &[f64]) -> f64 {
-    let total = values
-        .iter()
-        .fold(0.0, |a, b| a + b);
-    total / values.len()
+    let total = values.iter().fold(0.0, |a, b| a + *b);
+    total / values.len() as f64
 }
 
 fn main() {
     let values = [3.5, 0.3, 13.0, 11.7];
     println!("{}", average(&values));
-}
\ No newline at end of file
+}
diff --git a/exercises/generics/generics1.rs b/exercises/generics/generics1.rs
index d075a4d..a441ed2 100644
--- a/exercises/generics/generics1.rs
+++ b/exercises/generics/generics1.rs
@@ -1,10 +1,9 @@
 // This shopping list program isn't compiling! 
 // Use your knowledge of generics to fix it.
 
-// I AM NOT DONE
 
 fn main() {
-    let mut shopping_list: Vec<?> = Vec::new();
+    let mut shopping_list: Vec<&str> = Vec::new();
     shopping_list.push("milk");
 }
 
diff --git a/exercises/generics/generics2.rs b/exercises/generics/generics2.rs
index 1fe5041..57ae948 100644
--- a/exercises/generics/generics2.rs
+++ b/exercises/generics/generics2.rs
@@ -1,13 +1,12 @@
 // This powerful wrapper provides the ability to store a positive integer value.
 // Rewrite it using generics so that it supports wrapping ANY type.
 
-// I AM NOT DONE
-struct Wrapper<u32> {
-    value: u32
+struct Wrapper<T> {
+    value: T,
 }
 
-impl<u32> Wrapper<u32> {
-    pub fn new(value: u32) -> Self {
+impl<T> Wrapper<T> {
+    pub fn new(value: T) -> Self {
         Wrapper { value }
     }
 }
@@ -18,13 +17,11 @@ mod tests {
 
     #[test]
     fn store_u32_in_wrapper() {
-        assert_eq!(Wrapper::new(42).value,  42);
+        assert_eq!(Wrapper::new(42).value, 42);
     }
 
     #[test]
     fn store_str_in_wrapper() {
-        // TODO: Delete this assert and uncomment the one  below once you have  finished the exercise.
-        assert!(false);
-        // assert_eq!(Wrapper::new("Foo").value, "Foo");
+        assert_eq!(Wrapper::new("Foo").value, "Foo");
     }
-}
\ No newline at end of file
+}
diff --git a/exercises/generics/generics3.rs b/exercises/generics/generics3.rs
index cd3232a..8cd6b97 100644
--- a/exercises/generics/generics3.rs
+++ b/exercises/generics/generics3.rs
@@ -1,21 +1,24 @@
 // 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 
+// 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 to support alphabetical report cards, thereby making the second
 // test pass.
+use std::fmt::Display;
 
-// I AM NOT DONE
-pub struct ReportCard {
-    pub grade: f32,
+pub struct ReportCard<T> {
+    pub grade: T,
     pub student_name: String,
     pub student_age: u8,
 }
 
-impl ReportCard {
+impl<T: Display> ReportCard<T> {
     pub fn print(&self) -> String {
-        format!("{} ({}) - achieved a grade of {}", &self.student_name, &self.student_age, &self.grade)
+        format!(
+            "{} ({}) - achieved a grade of {}",
+            &self.student_name, &self.student_age, &self.grade
+        )
     }
 }
 
@@ -26,21 +29,27 @@ mod tests {
     #[test]
     fn generate_numeric_report_card() {
         let report_card = ReportCard {
-            grade: 2.1, 
-            student_name: "Tom Wriggle".to_string(), 
+            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");
+        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(), 
+            grade: "A+".to_string(),
+            student_name: "Gary Plotter".to_string(),
             student_age: 11,
         };
-        assert_eq!(report_card.print(), "Gary Plotter (11) - achieved a grade of A+");
+        assert_eq!(
+            report_card.print(),
+            "Gary Plotter (11) - achieved a grade of A+"
+        );
     }
-}
\ No newline at end of file
+}
diff --git a/exercises/standard_library_types/arc1.rs b/exercises/standard_library_types/arc1.rs
index 9784e84..a3a527f 100644
--- a/exercises/standard_library_types/arc1.rs
+++ b/exercises/standard_library_types/arc1.rs
@@ -4,20 +4,21 @@
 // somewhere. Try not to create any copies of the `numbers` Vec!
 // Execute `rustlings hint arc1` for hints :)
 
-// I AM NOT DONE
-
 use std::sync::Arc;
 use std::thread;
 
 fn main() {
     let numbers: Vec<_> = (0..100u32).collect();
-    let shared_numbers = // TODO
+    let shared_numbers = Arc::new(numbers);
     let mut joinhandles = Vec::new();
 
     for offset in 0..8 {
+        let child_numbers = shared_numbers.clone();
+
         joinhandles.push(thread::spawn(move || {
             let mut i = offset;
             let mut sum = 0;
+
             while i < child_numbers.len() {
                 sum += child_numbers[i];
                 i += 5;
diff --git a/exercises/standard_library_types/iterators2.rs b/exercises/standard_library_types/iterators2.rs
index a1274a2..2c50371 100644
--- a/exercises/standard_library_types/iterators2.rs
+++ b/exercises/standard_library_types/iterators2.rs
@@ -5,13 +5,14 @@
 // Step 3. Apply the `capitalize_first` function again to a list, but try and ensure it returns a single string
 // As always, there are hints if you execute `rustlings hint iterators2`!
 
-// I AM NOT DONE
+
+use std::str::Chars;
 
 pub fn capitalize_first(input: &str) -> String {
-    let mut c = input.chars();
+    let mut c: Chars = input.chars();
     match c.next() {
         None => String::new(),
-        Some(first) => first.collect::<String>() + c.as_str(),
+        Some(first) => first.to_uppercase().collect::<String>() + c.as_str(),
     }
 }
 
@@ -35,14 +36,14 @@ mod tests {
     #[test]
     fn test_iterate_string_vec() {
         let words = vec!["hello", "world"];
-        let capitalized_words: Vec<String> = // TODO
+        let capitalized_words: Vec<String> = words.iter().map(|&c| capitalize_first(c)).collect();
         assert_eq!(capitalized_words, ["Hello", "World"]);
     }
 
     #[test]
     fn test_iterate_into_string() {
         let words = vec!["hello", " ", "world"];
-        let capitalized_words = // TODO
+        let capitalized_words = words.iter().map(|&c| capitalize_first(c)).collect::<String>();
         assert_eq!(capitalized_words, "Hello World");
     }
 }
diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/standard_library_types/iterators3.rs
index 353cea6..e798cde 100644
--- a/exercises/standard_library_types/iterators3.rs
+++ b/exercises/standard_library_types/iterators3.rs
@@ -7,7 +7,6 @@
 // Execute `rustlings hint iterators3` to get some hints!
 // Have fun :-)
 
-// I AM NOT DONE
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum DivisionError {
@@ -24,7 +23,18 @@ pub struct NotDivisibleError {
 // This function should calculate `a` divided by `b` if `a` is
 // evenly divisible by b.
 // Otherwise, it should return a suitable error.
-pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {}
+pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
+    if b == 0 {
+        Err(DivisionError::DivideByZero)
+    } else if a % b != 0 {
+        Err(DivisionError::NotDivisible(NotDivisibleError {
+            dividend: a,
+            divisor: b,
+        }))
+    } else {
+        Ok(a / b)
+    }
+}
 
 #[cfg(test)]
 mod tests {
@@ -42,7 +52,7 @@ mod tests {
             divide(81, 6),
             Err(DivisionError::NotDivisible(NotDivisibleError {
                 dividend: 81,
-                divisor: 6
+                divisor: 6,
             }))
         );
     }
@@ -58,12 +68,12 @@ mod tests {
     }
 
     // Iterator exercises using your `divide` function
-    /*
+
     #[test]
     fn result_with_list() {
         let numbers = vec![27, 297, 38502, 81];
         let division_results = numbers.into_iter().map(|n| divide(n, 27));
-        let x //... Fill in here!
+        let x = division_results.collect::<Result<Vec<i32>, _>>();
         assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");
     }
 
@@ -71,8 +81,8 @@ mod tests {
     fn list_of_results() {
         let numbers = vec![27, 297, 38502, 81];
         let division_results = numbers.into_iter().map(|n| divide(n, 27));
-        let x //... Fill in here!
+        let x = division_results.collect::<Vec<Result<i32, DivisionError>>>();
         assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
     }
-    */
+
 }
diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/standard_library_types/iterators4.rs
index b945613..f38d374 100644
--- a/exercises/standard_library_types/iterators4.rs
+++ b/exercises/standard_library_types/iterators4.rs
@@ -1,6 +1,5 @@
 // iterators4.rs
 
-// I AM NOT DONE
 
 pub fn factorial(num: u64) -> u64 {
     // Complete this function to return factorial of num
@@ -12,6 +11,11 @@ pub fn factorial(num: u64) -> u64 {
     // For the most fun don't use:
     // - recursion
     // Execute `rustlings hint iterators4` for hints.
+
+    match num {
+        1 => 1,
+        n => n * factorial(n - 1)
+    }
 }
 
 #[cfg(test)]
diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs
index 1785e8c..c6c7e85 100644
--- a/exercises/threads/threads1.rs
+++ b/exercises/threads/threads1.rs
@@ -5,9 +5,10 @@
 // of "waiting..." and the program ends without timing out when running,
 // you've got it :)
 
-// I AM NOT DONE
 
 use std::sync::Arc;
+use std::sync::Mutex;
+use std::sync::MutexGuard;
 use std::thread;
 use std::time::Duration;
 
@@ -16,16 +17,18 @@ struct JobStatus {
 }
 
 fn main() {
-    let status = Arc::new(JobStatus { jobs_completed: 0 });
+    let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));
     let status_shared = status.clone();
     thread::spawn(move || {
-        for _ in 0..10 {
-            thread::sleep(Duration::from_millis(250));
-            status_shared.jobs_completed += 1;
+        for _ in 0..100 {
+            thread::sleep(Duration::from_millis(25));
+            let mut sharedJobStatus: MutexGuard<JobStatus>  = status_shared.lock().unwrap();
+            let curr_jobs_completed: u32 = sharedJobStatus.jobs_completed as u32;
+            *sharedJobStatus = JobStatus { jobs_completed: curr_jobs_completed + 1 };
         }
     });
-    while status.jobs_completed < 10 {
-        println!("waiting... ");
-        thread::sleep(Duration::from_millis(500));
+    while status.lock().unwrap().jobs_completed < 20 {
+        println!("waiting... {}", status.lock().unwrap().jobs_completed);
+        thread::sleep(Duration::from_millis(25));
     }
 }
diff --git a/exercises/traits/traits1.rs b/exercises/traits/traits1.rs
index 8253ef8..09c04d4 100644
--- a/exercises/traits/traits1.rs
+++ b/exercises/traits/traits1.rs
@@ -8,14 +8,15 @@
 // which appends "Bar" to any object
 // implementing this trait.
 
-// I AM NOT DONE
 trait AppendBar {
     fn append_bar(self) -> Self;
 }
 
 impl AppendBar for String {
-    //Add your code here
 
+    fn append_bar(self) -> Self {
+        self + "Bar"
+    }
 }
 
 fn main() {
@@ -41,4 +42,4 @@ mod tests {
         );
     }
 
-}
\ No newline at end of file
+}
diff --git a/exercises/traits/traits2.rs b/exercises/traits/traits2.rs
index 7f5014d..dbadf8e 100644
--- a/exercises/traits/traits2.rs
+++ b/exercises/traits/traits2.rs
@@ -1,25 +1,26 @@
 // traits2.rs
-// 
+//
 // Your task is to implement the trait
 // `AppendBar' for a vector of strings.
-// 
+//
 // To implement this trait, consider for
 // a moment what it means to 'append "Bar"'
 // to a vector of strings.
-// 
+//
 // No boiler plate code this time,
 // you can do this!
 
-// I AM NOT DONE
 
 trait AppendBar {
     fn append_bar(self) -> Self;
 }
 
-//TODO: Add your code here
-
-
-
+impl AppendBar for Vec<String> {
+    fn append_bar(mut self) -> Self {
+        self.push("Bar".to_string());
+        self
+    }
+}
 
 #[cfg(test)]
 mod tests {
@@ -31,5 +32,4 @@ mod tests {
         assert_eq!(foo.pop().unwrap(), String::from("Bar"));
         assert_eq!(foo.pop().unwrap(), String::from("Foo"));
     }
-
 }