Incorporate ConnyOnny's iterator exercise!
- Deciding not to have solutions in the tree right now, until I figure out a more general way to handle that. - The assertions work really great as tests, actually! - Simplifying a few of the side points-- I think they deserve their own exercises :)
This commit is contained in:
parent
d0f4ee1b39
commit
4bf727cbf7
|
@ -108,6 +108,14 @@ The [Concurrency](https://doc.rust-lang.org/stable/book/concurrency.html) sectio
|
|||
|
||||
- ["arc1.rs"](http://play.rust-lang.org/?code=%2F%2F+Make+this+code+compile+by+filling+in+a+value+for+%60shared_numbers%60+where+the%0A%2F%2F+TODO+comment+is+and+creating+an+initial+binding+for+%60child_numbers%60%0A%2F%2F+somewhere.+Try+not+to+create+any+copies+of+the+%60numbers%60+Vec%21%0A%2F%2F+Scroll+down+for+hints+%3A%29%0A%0Ause+std%3A%3Async%3A%3AArc%3B%0Ause+std%3A%3Athread%3B%0A%0Afn+main%28%29+%7B%0A++++let+numbers%3A+Vec%3C_%3E+%3D+%280..100u32%29.collect%28%29%3B%0A++++let+shared_numbers+%3D+%2F%2F+TODO%0A++++let+mut+joinhandles+%3D+Vec%3A%3Anew%28%29%3B%0A%0A++++for+offset+in+0..8+%7B%0A++++++++joinhandles.push%28%0A++++++++thread%3A%3Aspawn%28move+%7C%7C+%7B%0A++++++++++++let+mut+i+%3D+offset%3B%0A++++++++++++let+mut+sum+%3D+0%3B%0A++++++++++++while+i+%3C+child_numbers.len%28%29+%7B%0A++++++++++++++++sum+%2B%3D+child_numbers%5Bi%5D%3B%0A++++++++++++++++i+%2B%3D+5%3B%0A++++++++++++%7D%0A++++++++++++println%21%28%22Sum+of+offset+%7B%7D+is+%7B%7D%22%2C+offset%2C+sum%29%3B%0A++++++++%7D%29%29%3B%0A++++%7D%0A++++for+handle+in+joinhandles.into_iter%28%29+%7B%0A++++++++handle.join%28%29.unwrap%28%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Make+%60shared_numbers%60+be+an+%60Arc%60+from+the+numbers+vector.+Then%2C+in+order%0A%2F%2F+to+avoid+creating+a+copy+of+%60numbers%60%2C+you%27ll+need+to+create+%60child_numbers%60%0A%2F%2F+inside+the+loop+but+still+in+the+main+thread.%0A%0A%2F%2F+%60child_numbers%60+should+be+a+clone+of+the+Arc+of+the+numbers+instead+of+a%0A%2F%2F+thread-local+copy+of+the+numbers.%0A)
|
||||
|
||||
#### Iterators
|
||||
|
||||
Do not adjust your monitors-- iterators 1 and 2 are indeed missing. Iterator 3 is a bit challenging so we're leaving space for some exercises to lead up to it!
|
||||
|
||||
Check out the [Iterators chapter of the book](https://doc.rust-lang.org/stable/book/iterators.html) and the [Iterator docs](http://doc.rust-lang.org/stable/std/iter/trait.Iterator.html).
|
||||
|
||||
- ["iterator3.rs"](http://play.rust-lang.org/?code=%2F%2F+This+is+a+bigger+exercise+than+most+of+the+others%21+You+can+do+it%21%0A%2F%2F+Here+is+your+mission%2C+should+you+choose+to+accept+it%3A%0A%2F%2F+1.+Complete+the+divide+function+to+get+the+first+four+tests+to+pass%0A%2F%2F+2.+Uncomment+the+last+two+tests+and+get+them+to+pass+by+filling+in%0A%2F%2F++++values+for+%60x%60+using+%60division_results%60.%0A%2F%2F+Scroll+down+for+a+minor+hint+for+part+2%2C+and+scroll+down+further+for%0A%2F%2F+a+major+hint.%0A%2F%2F+Have+fun+%3A-%29%0A%0A%23%5Bderive%28Debug%2C+PartialEq%2C+Eq%29%5D%0Apub+enum+DivisionError+%7B%0A++++NotDivisible%28NotDivisibleError%29%2C%0A++++DivideByZero%2C%0A%7D%0A%0A%23%5Bderive%28Debug%2C+PartialEq%2C+Eq%29%5D%0Apub+struct+NotDivisibleError+%7B%0A++++dividend%3A+i32%2C%0A++++divisor%3A+i32%2C%0A%7D%0A%0A%2F%2F+This+function+should+calculate+%60a%60+divided+by+%60b%60+if+%60a%60+is%0A%2F%2F+evenly+divisible+by+b.%0A%2F%2F+Otherwise%2C+it+should+return+a+suitable+error.%0Apub+fn+divide%28a%3A+i32%2C+b%3A+i32%29+-%3E+Result%3Ci32%2C+DivisionError%3E+%7B%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%2F%2F+Tests+that+verify+your+%60divide%60+function+implementation%0A++++%23%5Btest%5D%0A++++fn+test_success%28%29+%7B%0A++++++++assert_eq%21%28divide%2881%2C+9%29%2C+Ok%289%29%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+test_not_divisible%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++divide%2881%2C+6%29%2C%0A++++++++++++Err%28DivisionError%3A%3ANotDivisible%28NotDivisibleError%7B%0A++++++++++++++++dividend%3A+81%2C%0A++++++++++++++++divisor%3A+6%0A++++++++++++%7D%29%29%0A++++++++%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+test_divide_by_0%28%29+%7B%0A++++++++assert_eq%21%28divide%2881%2C+0%29%2C+Err%28DivisionError%3A%3ADivideByZero%29%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+test_divide_0_by_something%28%29+%7B%0A++++++++assert_eq%21%28divide%280%2C+81%29%2C+Ok%280%29%29%3B%0A++++%7D%0A%0A++++%2F%2F+Iterator+exercises+using+your+%60divide%60+function%0A++++%2F*%0A++++%23%5Btest%5D%0A++++fn+result_with_list%28%29+%7B%0A++++++++let+numbers+%3D+vec%21%5B27%2C+297%2C+38502%2C+81%5D%3B%0A++++++++let+division_results+%3D+numbers.into_iter%28%29.map%28%7Cn%7C+divide%28n%2C+27%29%29%3B%0A++++++++let+x+%2F%2F...+Fill+in+here%21%0A++++++++assert_eq%21%28format%21%28%22%7B%3A%3F%7D%22%2C+x%29%2C+%22Ok%28%5B1%2C+11%2C+1426%2C+3%5D%29%22%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+list_of_results%28%29+%7B%0A++++++++let+numbers+%3D+vec%21%5B27%2C+297%2C+38502%2C+81%5D%3B%0A++++++++let+division_results+%3D+numbers.into_iter%28%29.map%28%7Cn%7C+divide%28n%2C+27%29%29%3B%0A++++++++let+x+%2F%2F...+Fill+in+here%21%0A++++++++assert_eq%21%28format%21%28%22%7B%3A%3F%7D%22%2C+x%29%2C+%22%5BOk%281%29%2C+Ok%2811%29%2C+Ok%281426%29%2C+Ok%283%29%5D%22%29%3B%0A++++%7D%0A++++*%2F%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Minor+hint%3A+In+each+of+the+two+cases+in+the+match+in+main%2C+you+can+create+x+with+either+a+%27turbofish%27+or+by+hinting+the+type+of+x+to+the+compiler.+You+may+try+both.%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Major+hint%3A+Have+a+look+at+the+Iter+trait+and+at+the+explanation+of+its+collect+function.+Especially+the+part+about+Result+is+interesting.%0A)
|
||||
|
||||
### Threads
|
||||
|
||||
See [the Dining Philosophers example](https://doc.rust-lang.org/stable/book/dining-philosophers.html) and the [Concurrency Chapter](https://doc.rust-lang.org/stable/book/concurrency.html) from the book.
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
// 1. Complete the divide function
|
||||
// 2. Uncomment and complete the second part of the main function
|
||||
// For part 2 there is a minor hint around line 100 and a major hint around line 128
|
||||
// There are some final comments for when you are done around line 150
|
||||
// Have fun :-)
|
||||
|
||||
|
||||
// In production code you would not derive Debug, but implement it manually to get a better error message.
|
||||
#[derive(Debug,PartialEq,Eq)]
|
||||
enum DivisionError {
|
||||
NotDivisible(NotDivisibleError),
|
||||
DivideByZero,
|
||||
}
|
||||
#[derive(Debug,PartialEq,Eq)]
|
||||
struct NotDivisibleError {
|
||||
divident: i32,
|
||||
divisor: i32,
|
||||
}
|
||||
|
||||
// This function calculates a/b if a is divisible by b.
|
||||
// Otherwise it returns a suitable error.
|
||||
fn divide(a: i32, b: i32) -> Result<i32,DivisionError> {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
enum OperationMode {
|
||||
ListOfResults,
|
||||
ResultWithList,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// These asserts check that your `divide` function works.
|
||||
// In production code these would be tests
|
||||
assert_eq!(divide(81,9),Ok(9));
|
||||
assert_eq!(divide(81,6),Err(DivisionError::NotDivisible(NotDivisibleError{divident:81,divisor:6})));
|
||||
assert_eq!(divide(81,0),Err(DivisionError::DivideByZero));
|
||||
assert_eq!(divide(0,81),Ok(0));
|
||||
println!("Your divide function seems to work! Good Job.");
|
||||
|
||||
/* Second part of main. Uncomment to continue.
|
||||
// Don't change these numbers. It will break the assertions later in the code.
|
||||
let numbers = vec![27,297,38502,81];
|
||||
|
||||
let division_results = // Do not convert the results into a Vec yet. Leave them iterable for now.
|
||||
let operation_mode = OperationMode::ResultWithList;
|
||||
match operation_mode {
|
||||
OperationMode::ResultWithList => {
|
||||
|
||||
println!("{:?}", x);
|
||||
assert_eq!(format!("{:?}",x), "Ok([1, 11, 1426, 3])");
|
||||
},
|
||||
OperationMode::ListOfResults => {
|
||||
|
||||
println!("{:?}", x);
|
||||
assert_eq!(format!("{:?}",x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
|
||||
},
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Minor hint: In each of the two cases in the match in main, you can create x with either a 'turbofish' or by hinting the type of x to the compiler. You may try both.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Major hint: Have a look at the Iter trait and at the explanation of its collect function. Especially the part about Result is interesting.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Final comments
|
||||
// When you call the function `print_result_with_list` with x, you don't need any type annotations on x anymore.
|
||||
// The compiler can infer its type through the function's input type.
|
||||
|
||||
#[allow(dead_code)]
|
||||
// Don't use this function to solve the exercise
|
||||
fn print_result_with_list(r: Result<Vec<i32>,DivisionError>) {
|
||||
// side quest: why is there no semicolon in this function?
|
||||
match r {
|
||||
Ok(v) => println!("All numbers were successfully divided: {:?}", v),
|
||||
Err(e) => match e {
|
||||
DivisionError::NotDivisible(nde) => println!("Failed to divide {} by {}: Not divisible!", nde.divident, nde.divisor),
|
||||
DivisionError::DivideByZero => println!("Can't divide by zero"),
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
|
||||
// In production code you would not derive Debug, but implement it manually to get a better error message.
|
||||
#[derive(Debug,PartialEq,Eq)]
|
||||
enum DivisionError {
|
||||
NotDivisible(NotDivisibleError),
|
||||
DivideByZero,
|
||||
}
|
||||
#[derive(Debug,PartialEq,Eq)]
|
||||
struct NotDivisibleError {
|
||||
divident: i32,
|
||||
divisor: i32,
|
||||
}
|
||||
|
||||
// This function calculates a/b if a is divisible by b.
|
||||
// Otherwise it returns a suitable error.
|
||||
fn divide(a: i32, b: i32) -> Result<i32,DivisionError> {
|
||||
if b == 0 {
|
||||
return Err(DivisionError::DivideByZero);
|
||||
}
|
||||
match a % b {
|
||||
0 => Ok(a/b),
|
||||
_ => Err(DivisionError::NotDivisible(NotDivisibleError{divident:a, divisor:b})),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
enum OperationMode {
|
||||
ListOfResults,
|
||||
ResultWithList,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn print_result_with_list(r: Result<Vec<i32>,DivisionError>) {
|
||||
// side quest: why is there no semicolon in this function?
|
||||
match r {
|
||||
Ok(v) => println!("All numbers were successfully divided: {:?}", v),
|
||||
Err(e) => match e {
|
||||
DivisionError::NotDivisible(nde) => println!("Failed to divide {} by {}: Not divisible!", nde.divident, nde.divisor),
|
||||
DivisionError::DivideByZero => println!("Can't divide by zero"),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// These asserts check that your `divide` function works.
|
||||
// In production code these would be tests
|
||||
assert_eq!(divide(81,9),Ok(9));
|
||||
assert_eq!(divide(81,6),Err(DivisionError::NotDivisible(NotDivisibleError{divident:81,divisor:6})));
|
||||
assert_eq!(divide(81,0),Err(DivisionError::DivideByZero));
|
||||
println!("Your divide function seems to work! Good Job.");
|
||||
// Don't change these numbers. It will break the assertions later in the code.
|
||||
let numbers = vec![27,297,38502,81];
|
||||
let numbers_iterator = numbers.into_iter();
|
||||
let division_results = numbers_iterator.map(|n| divide(n, 27));
|
||||
let operation_mode = OperationMode::ResultWithList; // you may change this
|
||||
match operation_mode {
|
||||
OperationMode::ResultWithList => {
|
||||
let x : Result<Vec<_>,_> = division_results.collect();
|
||||
//print_result_with_list(x);
|
||||
assert_eq!(format!("{:?}",x), "Ok([1, 11, 1426, 3])");
|
||||
},
|
||||
OperationMode::ListOfResults => {
|
||||
let x : Vec<_> = division_results.collect();
|
||||
println!("{:?}", x);
|
||||
assert_eq!(format!("{:?}",x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
|
||||
},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
// This is a bigger exercise than most of the others! You can do it!
|
||||
// Here is your mission, should you choose to accept it:
|
||||
// 1. Complete the divide function to get the first four tests to pass
|
||||
// 2. Uncomment the last two tests and get them to pass by filling in
|
||||
// values for `x` using `division_results`.
|
||||
// Scroll down for a minor hint for part 2, and scroll down further for
|
||||
// a major hint.
|
||||
// Have fun :-)
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DivisionError {
|
||||
NotDivisible(NotDivisibleError),
|
||||
DivideByZero,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct NotDivisibleError {
|
||||
dividend: i32,
|
||||
divisor: i32,
|
||||
}
|
||||
|
||||
// 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> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// Tests that verify your `divide` function implementation
|
||||
#[test]
|
||||
fn test_success() {
|
||||
assert_eq!(divide(81, 9), Ok(9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_divisible() {
|
||||
assert_eq!(
|
||||
divide(81, 6),
|
||||
Err(DivisionError::NotDivisible(NotDivisibleError{
|
||||
dividend: 81,
|
||||
divisor: 6
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_divide_by_0() {
|
||||
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_divide_0_by_something() {
|
||||
assert_eq!(divide(0, 81), Ok(0));
|
||||
}
|
||||
|
||||
// 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!
|
||||
assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");
|
||||
}
|
||||
|
||||
#[test]
|
||||
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!
|
||||
assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Minor hint: In each of the two cases in the match in main, you can create x with either a 'turbofish' or by hinting the type of x to the compiler. You may try both.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Major hint: Have a look at the Iter trait and at the explanation of its collect function. Especially the part about Result is interesting.
|
Loading…
Reference in New Issue