diff --git a/exercises/clippy/clippy1.rs b/exercises/clippy/clippy1.rs index bad4689..6866b13 100644 --- a/exercises/clippy/clippy1.rs +++ b/exercises/clippy/clippy1.rs @@ -6,15 +6,12 @@ // check clippy's suggestions from the output to solve the exercise. // Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - use std::f32; fn main() { - let pi = 3.14f32; let radius = 5.00f32; - let area = pi * f32::powi(radius, 2); + let area = f32::consts::PI * f32::powi(radius, 2); println!( "The area of a circle with radius {:.2} is {:.5}!", diff --git a/exercises/clippy/clippy2.rs b/exercises/clippy/clippy2.rs index dac40db..48d8244 100644 --- a/exercises/clippy/clippy2.rs +++ b/exercises/clippy/clippy2.rs @@ -1,12 +1,10 @@ // clippy2.rs // Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - fn main() { let mut res = 42; let option = Some(12); - for x in option { + if let Some(x) = option { res += x; } println!("{}", res); diff --git a/exercises/clippy/clippy3.rs b/exercises/clippy/clippy3.rs index b0159eb..b786e54 100644 --- a/exercises/clippy/clippy3.rs +++ b/exercises/clippy/clippy3.rs @@ -1,28 +1,26 @@ // 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(); + if let Some(x) = my_option { + x } let my_arr = &[ - -1, -2, -3 + -1, -2, -3, -4, -5, -6 ]; println!("My array! Here it is: {:?}", my_arr); - let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5); + let mut my_empty_vec = vec![1, 2, 3, 4, 5]; + my_empty_vec.clear(); println!("This Vec is empty, see? {:?}", my_empty_vec); let mut value_a = 45; let mut value_b = 66; // Let's swap these two! - value_a = value_b; - value_b = value_a; + std::mem::swap(&mut value_a, &mut value_b); println!("value a: {}; value b: {}", value_a, value_b); } diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs index 9f47973..3837942 100644 --- a/exercises/conversions/as_ref_mut.rs +++ b/exercises/conversions/as_ref_mut.rs @@ -3,24 +3,22 @@ // 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 - // Obtain the number of bytes (not characters) in the given argument // Add the AsRef trait appropriately as a trait bound -fn byte_counter(arg: T) -> usize { +fn byte_counter>(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(arg: T) -> usize { +fn char_counter>(arg: T) -> usize { arg.as_ref().chars().count() } // Squares a number using AsMut. Add the trait bound as is appropriate and // implement the function body. -fn num_sq(arg: &mut T) { - ??? +fn num_sq>(arg: &mut T) { + *arg.as_mut() = arg.as_mut().pow(2); } #[cfg(test)] diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs index 6c272c3..02128a1 100644 --- a/exercises/conversions/from_into.rs +++ b/exercises/conversions/from_into.rs @@ -35,10 +35,32 @@ impl Default for Person { // If while parsing the age, something goes wrong, then return the default of Person // Otherwise, then return an instantiated Person object with the results -// I AM NOT DONE - impl From<&str> for Person { fn from(s: &str) -> Person { + if s.len() == 0 { + return Default::default(); + } + + let mut person: Person = Default::default(); + let parts: Vec<&str> = s.split(",").collect(); + + if parts.len() != 2 { + return Default::default(); + } + + if parts[0].len() > 0 { + person.name = parts[0].to_string(); + } else { + return Default::default(); + } + + if let Ok(n) = parts[1].parse::() { + person.age = n; + } else { + return Default::default(); + } + + person } } diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index fe16815..fec6be0 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -28,8 +28,6 @@ enum ParsePersonError { ParseInt(ParseIntError), } -// I AM NOT DONE - // Steps: // 1. If the length of the provided string is 0, an error should be returned // 2. Split the given string on the commas present in it @@ -46,6 +44,24 @@ enum ParsePersonError { impl FromStr for Person { type Err = ParsePersonError; fn from_str(s: &str) -> Result { + if s.len() == 0 { + return Err(ParsePersonError::Empty) + } + + let parts: Vec<&str> = s.split(",").collect(); + + if parts.len() != 2 { + return Err(ParsePersonError::BadLen) + } + + if parts[0].len() < 1 { + return Err(ParsePersonError::NoName) + } + + match (parts[1].parse::()) { + Ok(age) => Ok(Person { name: parts[0].to_string(), age }), + Err(x) => Err(ParsePersonError::ParseInt(x)) + } } } diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index fa98bc9..9a2d976 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -23,8 +23,6 @@ enum IntoColorError { IntConversion, } -// I AM NOT DONE - // Your task is to complete this implementation // and return an Ok result of inner type Color. // You need to create an implementation for a tuple of three integers, @@ -38,6 +36,13 @@ enum IntoColorError { impl TryFrom<(i16, i16, i16)> for Color { type Error = IntoColorError; fn try_from(tuple: (i16, i16, i16)) -> Result { + let range = 0..=255; + + if !range.contains(&tuple.0) || !range.contains(&tuple.1) || !range.contains(&tuple.2) { + return Err(IntoColorError::IntConversion); + } + + Ok(Color { red: tuple.0 as u8, green: tuple.1 as u8, blue: tuple.2 as u8 }) } } @@ -45,6 +50,7 @@ impl TryFrom<(i16, i16, i16)> for Color { impl TryFrom<[i16; 3]> for Color { type Error = IntoColorError; fn try_from(arr: [i16; 3]) -> Result { + Color::try_from(&arr[..]) } } @@ -52,6 +58,17 @@ impl TryFrom<[i16; 3]> for Color { impl TryFrom<&[i16]> for Color { type Error = IntoColorError; fn try_from(slice: &[i16]) -> Result { + let range = 0..=255; + + if slice.len() != 3 { + return Err(IntoColorError::BadLen) + } + + if slice.iter().any(|n| !range.contains(n)) { + return Err(IntoColorError::IntConversion) + } + + Ok(Color { red: slice[0] as u8, green: slice[1] as u8, blue: slice[2] as u8 }) } } diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs index 8c9b711..0d961ca 100644 --- a/exercises/conversions/using_as.rs +++ b/exercises/conversions/using_as.rs @@ -6,11 +6,9 @@ // and returns the proper type. // Execute `rustlings hint using_as` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - fn average(values: &[f64]) -> f64 { let total = values.iter().sum::(); - total / values.len() + total / values.len() as f64 } fn main() { diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs index 634d0a7..3c0696a 100644 --- a/exercises/macros/macros1.rs +++ b/exercises/macros/macros1.rs @@ -1,8 +1,6 @@ // macros1.rs // Execute `rustlings hint macros1` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - macro_rules! my_macro { () => { println!("Check out my macro!"); @@ -10,5 +8,5 @@ macro_rules! my_macro { } fn main() { - my_macro(); + my_macro!(); } diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs index f6092ca..3dd7108 100644 --- a/exercises/macros/macros2.rs +++ b/exercises/macros/macros2.rs @@ -1,14 +1,12 @@ // macros2.rs // Execute `rustlings hint macros2` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - -fn main() { - my_macro!(); -} - macro_rules! my_macro { () => { println!("Check out my macro!"); }; } + +fn main() { + my_macro!(); +} diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs index 106f1c6..302da07 100644 --- a/exercises/macros/macros3.rs +++ b/exercises/macros/macros3.rs @@ -2,8 +2,7 @@ // Make me compile, without taking the macro out of the module! // Execute `rustlings hint macros3` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - +#[macro_use] mod macros { macro_rules! my_macro { () => { diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index c1fc5e8..9e7a225 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -1,12 +1,10 @@ // macros4.rs // Execute `rustlings hint macros4` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE - macro_rules! my_macro { () => { println!("Check out my macro!"); - } + }; ($val:expr) => { println!("Look at this other macro: {}", $val); } diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index e59f4ce..cc1c059 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -2,8 +2,6 @@ // 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::thread; use std::time::Duration; @@ -12,20 +10,20 @@ fn main() { let mut handles = vec![]; for i in 0..10 { - thread::spawn(move || { + handles.push(thread::spawn(move || { thread::sleep(Duration::from_millis(250)); 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? + handle.join(); 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 index d0f8578..5bfcbaf 100644 --- a/exercises/threads/threads2.rs +++ b/exercises/threads/threads2.rs @@ -3,9 +3,7 @@ // 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::sync::{Arc,Mutex}; use std::thread; use std::time::Duration; @@ -14,13 +12,14 @@ struct JobStatus { } fn main() { - let status = Arc::new(JobStatus { jobs_completed: 0 }); + let status = Arc::new(Mutex::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 + let mut status_shared = status_shared.lock().unwrap(); status_shared.jobs_completed += 1; }); handles.push(handle); @@ -29,6 +28,6 @@ fn main() { 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 {}", ???); + println!("jobs completed {}", status.lock().unwrap().jobs_completed); } } diff --git a/exercises/threads/threads3.rs b/exercises/threads/threads3.rs index 27e9908..73080a8 100644 --- a/exercises/threads/threads3.rs +++ b/exercises/threads/threads3.rs @@ -1,8 +1,6 @@ // 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; @@ -28,11 +26,13 @@ fn send_tx(q: Queue, tx: mpsc::Sender) -> () { let qc = Arc::new(q); let qc1 = qc.clone(); let qc2 = qc.clone(); + let tx1 = tx.clone(); + let tx2 = tx.clone(); thread::spawn(move || { for val in &qc1.first_half { println!("sending {:?}", val); - tx.send(*val).unwrap(); + tx1.send(*val).unwrap(); thread::sleep(Duration::from_secs(1)); } }); @@ -40,7 +40,7 @@ fn send_tx(q: Queue, tx: mpsc::Sender) -> () { thread::spawn(move || { for val in &qc2.second_half { println!("sending {:?}", val); - tx.send(*val).unwrap(); + tx2.send(*val).unwrap(); thread::sleep(Duration::from_secs(1)); } });