Skip to content

Commit b58936a

Browse files
committed
Answers for standard_library_types
iterators4.rs was particularly instructive. I started out by searching for the initial C recursion and for loop versions and tried to use a range iteration but couldn't figure the syntax. So I created the first 7 answers and then used hint. I then seached for: how to use iterator for side effects only https://www.google.com/search?q=how+to+use+iterator+for+side+effects+only+in+rust And saw this: rust-lang/rust#44546 (comment) And: rust-lang/rust#44546 (comment) And with that I implemented Answer 8 But still wasn't happy as I felt there must be a better way where I didn't need to throw away things. So I looking at the iterator documentation: https://doc.rust-lang.org/std/iter/trait.Iterator.html I saw "fold" and low and behold that was exactly what I needed! Then I saw "fold_first" and it was "simpler" as the first value in the range is the initial value for the accumulator so fold_first only has one parameters not two. But fold_first returns an Option which means I need to return the unwrap(). Anyway both Answers 9 and 10 are simpler then any other solution! I do wonder which is fastest.
1 parent 8bab9fe commit b58936a

File tree

6 files changed

+233
-25
lines changed

6 files changed

+233
-25
lines changed

exercises/standard_library_types/arc1.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@
44
// somewhere. Try not to create any copies of the `numbers` Vec!
55
// Execute `rustlings hint arc1` for hints :)
66

7-
// I AM NOT DONE
7+
// I AM DONE
88

99
#![forbid(unused_imports)] // Do not change this, (or the next) line.
1010
use std::sync::Arc;
1111
use std::thread;
1212

1313
fn main() {
14-
let numbers: Vec<_> = (0..100u32).collect();
15-
let shared_numbers = // TODO
14+
let numbers: Vec<_> = (0..100u64).collect();
15+
let shared_numbers = Arc::new(numbers);
1616
let mut joinhandles = Vec::new();
1717

18+
// Answer 1
1819
for offset in 0..8 {
20+
let child_numbers = shared_numbers.clone();
1921
joinhandles.push(thread::spawn(move || {
2022
let mut i = offset;
2123
let mut sum = 0;
@@ -26,6 +28,25 @@ fn main() {
2628
println!("Sum of offset {} is {}", offset, sum);
2729
}));
2830
}
31+
32+
//// Answer 2
33+
//let threads = 10;
34+
//let shard_size = shared_numbers.len() / threads;
35+
//if shared_numbers.len() % threads != 0 {
36+
// panic!("shard_size isn't a multiple of numbers.len");
37+
//}
38+
//for offset in 0..threads {
39+
// let child_numbers = shared_numbers.clone();
40+
// joinhandles.push(thread::spawn(move || {
41+
// let base = shard_size * offset;
42+
// let mut sum = 0;
43+
// for i in 0..shard_size {
44+
// sum += child_numbers[base + i];
45+
// }
46+
// println!("Sum of offset {} is {}", offset, sum);
47+
// }));
48+
//}
49+
2950
for handle in joinhandles.into_iter() {
3051
handle.join().unwrap();
3152
}

exercises/standard_library_types/box1.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
//
1717
// Execute `rustlings hint box1` for hints :)
1818

19-
// I AM NOT DONE
19+
// I AM DONE
2020

2121
#[derive(PartialEq, Debug)]
2222
pub enum List {
23-
Cons(i32, List),
23+
Cons(i32, Box<List>),
2424
Nil,
2525
}
2626

@@ -33,11 +33,12 @@ fn main() {
3333
}
3434

3535
pub fn create_empty_list() -> List {
36-
unimplemented!()
36+
List::Nil
3737
}
3838

3939
pub fn create_non_empty_list() -> List {
40-
unimplemented!()
40+
//List::Cons(1, Box::new(List::Nil))
41+
List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))))
4142
}
4243

4344
#[cfg(test)]

exercises/standard_library_types/iterators1.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@
88
//
99
// Execute `rustlings hint iterators1` for hints :D
1010

11-
// I AM NOT DONE
11+
// I AM DONE
1212

1313
fn main () {
1414
let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"];
1515

16-
let mut my_iterable_fav_fruits = ???; // TODO: Step 1
16+
let mut my_iterable_fav_fruits = my_fav_fruits.iter(); // TODO: Step 1
1717

1818
assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana"));
19-
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 2
19+
assert_eq!(my_iterable_fav_fruits.next(), Some(&"custard apple")); // TODO: Step 2
2020
assert_eq!(my_iterable_fav_fruits.next(), Some(&"avocado"));
21-
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 2.1
21+
assert_eq!(my_iterable_fav_fruits.next(), Some(&"peach")); // TODO: Step 2.1
2222
assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry"));
23-
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 3
23+
assert_eq!(my_iterable_fav_fruits.next(), None); // TODO: Step 3
24+
// iterator next() continues to return no
25+
assert_eq!(my_iterable_fav_fruits.next(), None); // TODO: Step 3
2426
}

exercises/standard_library_types/iterators2.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@
77
// Try to ensure it returns a single string.
88
// As always, there are hints if you execute `rustlings hint iterators2`!
99

10-
// I AM NOT DONE
10+
// I AM DONE
1111

1212
pub fn capitalize_first(input: &str) -> String {
1313
let mut c = input.chars();
1414
match c.next() {
1515
None => String::new(),
16-
Some(first) => first.collect::<String>() + c.as_str(),
16+
Some(first) => first.to_uppercase().collect::<String>() + c.as_str(),
1717
}
1818
}
1919

20+
pub fn capitalize_words(input: Vec<&str>) -> Vec<String> {
21+
input.iter().map(|w| { capitalize_first(w) }).collect()
22+
}
23+
2024
#[cfg(test)]
2125
mod tests {
2226
use super::*;
@@ -37,14 +41,14 @@ mod tests {
3741
#[test]
3842
fn test_iterate_string_vec() {
3943
let words = vec!["hello", "world"];
40-
let capitalized_words: Vec<String> = // TODO
44+
let capitalized_words: Vec<String> = capitalize_words(words);
4145
assert_eq!(capitalized_words, ["Hello", "World"]);
4246
}
4347

4448
#[test]
4549
fn test_iterate_into_string() {
4650
let words = vec!["hello", " ", "world"];
47-
let capitalized_words = // TODO
51+
let capitalized_words: String = capitalize_words(words).join("");
4852
assert_eq!(capitalized_words, "Hello World");
4953
}
5054
}

exercises/standard_library_types/iterators3.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// Execute `rustlings hint iterators3` to get some hints!
88
// Have fun :-)
99

10-
// I AM NOT DONE
10+
// I AM DONE
1111

1212
#[derive(Debug, PartialEq, Eq)]
1313
pub enum DivisionError {
@@ -24,7 +24,15 @@ pub struct NotDivisibleError {
2424
// This function should calculate `a` divided by `b` if `a` is
2525
// evenly divisible by b.
2626
// Otherwise, it should return a suitable error.
27-
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {}
27+
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
28+
if b == 0 {
29+
return Err(DivisionError::DivideByZero);
30+
}
31+
if (a % b) != 0 {
32+
return Err(DivisionError::NotDivisible(NotDivisibleError {dividend: a, divisor: b}));
33+
}
34+
Ok(a / b)
35+
}
2836

2937
#[cfg(test)]
3038
mod tests {
@@ -46,7 +54,6 @@ mod tests {
4654
}))
4755
);
4856
}
49-
5057
#[test]
5158
fn test_divide_by_0() {
5259
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
@@ -56,23 +63,22 @@ mod tests {
5663
fn test_divide_0_by_something() {
5764
assert_eq!(divide(0, 81), Ok(0));
5865
}
59-
6066
// Iterator exercises using your `divide` function
61-
/*
67+
6268
#[test]
6369
fn result_with_list() {
6470
let numbers = vec![27, 297, 38502, 81];
71+
//let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<Result<i32, DivisionError>>();
6572
let division_results = numbers.into_iter().map(|n| divide(n, 27));
66-
let x //... Fill in here!
73+
let x: Result<Vec<i32>, _> = division_results.collect(); //... Fill in here!
6774
assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");
6875
}
6976

7077
#[test]
7178
fn list_of_results() {
7279
let numbers = vec![27, 297, 38502, 81];
7380
let division_results = numbers.into_iter().map(|n| divide(n, 27));
74-
let x //... Fill in here!
81+
let x: Vec<Result<i32, _>> = division_results.collect();
7582
assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
7683
}
77-
*/
7884
}

exercises/standard_library_types/iterators4.rs

Lines changed: 175 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,147 @@
1+
#![feature(iterator_fold_self)]
12
// iterators4.rs
23

3-
// I AM NOT DONE
4+
// I AM DONE
5+
6+
pub fn recursive(num: u64) -> u64 {
7+
let mut fact = num;
8+
if num > 1 {
9+
fact = num * recursive(num - 1)
10+
}
11+
println!("recursive: num={} fact={}", num, fact);
12+
fact
13+
}
14+
15+
pub fn simplest_recursive(num: u64) -> u64 {
16+
if num > 1 {
17+
num * simplest_recursive(num - 1)
18+
} else {
19+
num
20+
}
21+
}
22+
23+
pub fn match_recursive(num: u64) -> u64 {
24+
match num {
25+
n if n > 1 => n * match_recursive(n - 1),
26+
n => n,
27+
}
28+
}
29+
30+
pub fn for_in(num: u64) -> u64 {
31+
let mut fact = 1;
32+
for i in 1..num+1 {
33+
fact *= i;
34+
println!("for_in: num={} fact={}", num, fact);
35+
}
36+
fact
37+
}
38+
39+
// Create iterable version of Factorial
40+
41+
struct Factorial {
42+
num: u64,
43+
factorial: u64,
44+
}
45+
46+
impl Factorial {
47+
fn new(num: u64) -> Factorial {
48+
Factorial {
49+
num,
50+
factorial: 1
51+
}
52+
}
53+
}
54+
55+
impl Iterator for Factorial {
56+
type Item = u64;
57+
58+
fn next(&mut self) -> Option<Self::Item> {
59+
println!("Factorial::next:+ self.num={}", self.num);
60+
if self.num > 0 {
61+
self.factorial *= self.num;
62+
self.num -= 1;
63+
println!("Factorial::next:- Some self.factorial={}", self.factorial);
64+
return Some(self.factorial)
65+
} else {
66+
println!("Factorial::next:- None self.factorial={}", self.factorial);
67+
return None
68+
}
69+
}
70+
}
71+
72+
pub fn loop_next_iterator(num: u64) -> u64 {
73+
let mut f = Factorial::new(num);
74+
loop {
75+
let n = f.next();
76+
if n == None {
77+
break;
78+
}
79+
println!("iterator: f.next()={}", n.unwrap());
80+
}
81+
println!("iterator:- f.factorial={}", f.factorial);
82+
f.factorial
83+
}
84+
85+
pub fn for_in_iterator(num: u64) -> u64 {
86+
println!("iterator:+ num={}", num);
87+
let f = Factorial::new(num);
88+
let mut x: u64 = 1;
89+
for curf in f {
90+
println!("iterator: curf={}", curf);
91+
x = curf;
92+
}
93+
println!("iterator:- x={}", x);
94+
x
95+
}
96+
97+
pub fn while_next_iterator(num: u64) -> u64 {
98+
let mut f = Factorial::new(num);
99+
while f.next() != None {}
100+
f.factorial
101+
}
102+
103+
pub fn range_for_each_iterator(num: u64) -> u64 {
104+
// "rf" is a a reference to mutable fact
105+
// which is captured by the map closure.
106+
//let mut fact: u64 = 1;
107+
//let rf = &mut fact;
108+
//(1..num+1).map(|n| {
109+
// *rf *= n;
110+
// println!("n={} *rf={}", n, *rf);
111+
//} ).for_each(drop);
112+
//fact
113+
114+
// Turns out you don't need "rf", I'm guessing because fact
115+
// is on the left side of "=" and therfore is areference.
116+
let mut fact: u64 = 1;
117+
(1..num+1).map(|n| {
118+
fact *= n;
119+
//println!("n={} fact={}", n, fact);
120+
} ).for_each(drop);
121+
fact
122+
}
123+
124+
pub fn range_fold_iterator(num: u64) -> u64 {
125+
(1..num+1).fold(1, |fact, n| fact * n)
126+
127+
//// For debugging add a println
128+
//(1..num+1).fold(1, |fact, n| {
129+
// let f = fact * n;
130+
// println!("n={} f={}", n, f);
131+
// f
132+
//} )
133+
}
134+
135+
pub fn range_fold_first_iterator(num: u64) -> u64 {
136+
(1..num+1).fold_first(|fact, n| fact * n).unwrap()
137+
138+
//// For debugging add a println
139+
//(1..num+1).fold_first(|fact, n| {
140+
// let f = fact * n;
141+
// println!("n={} f={}", n, f);
142+
// f
143+
//} ).unwrap()
144+
}
4145

5146
pub fn factorial(num: u64) -> u64 {
6147
// Complete this function to return the factorial of num
@@ -12,7 +153,40 @@ pub fn factorial(num: u64) -> u64 {
12153
// For an extra challenge, don't use:
13154
// - recursion
14155
// Execute `rustlings hint iterators4` for hints.
156+
157+
// Answer 1 recursive
158+
//recursive(num)
159+
160+
// Answer 2 simplest recursive
161+
//simplest_recursive(num)
162+
163+
// Answer 3 match recursive
164+
//match_recursive(num)
165+
166+
// Answer 4 for_in no recursion
167+
//for_in(num)
168+
169+
// Answer 5 iterate using loop
170+
//loop_next_iterator(num)
171+
172+
// Answer 6 iterate using for in
173+
//for_in_iterator(num)
174+
175+
// Answer 7 iterate using while
176+
//while_next_iterator(num)
177+
178+
// Answer 8 Iterate using range and for_each
179+
//range_for_each_iterator(num)
180+
181+
// Answer 9 Iterate using range and fold
182+
// THIS IS THE BEST ANSWER, or maybe fold_first below.
183+
//range_fold_iterator(num)
184+
185+
// Answer 10 Iterate using range and fold_first
186+
// THIS IS THE BEST ANSWER :)
187+
range_fold_first_iterator(num)
15188
}
189+
16190

17191
#[cfg(test)]
18192
mod tests {

0 commit comments

Comments
 (0)