summaryrefslogtreecommitdiff
path: root/exercises
diff options
context:
space:
mode:
authorEmmanuel Roullit <eroullit@github.com>2023-02-25 17:11:43 +0100
committerGitHub <noreply@github.com>2023-02-25 17:11:43 +0100
commitfcadbfc70d578e4a993711d5a7f1737aebd6b3ce (patch)
tree897142c1904755a43aefce56695c0b8186381e69 /exercises
parentb653d4848a52701d2240f130ab74c158dd5d7069 (diff)
parent701b4bef51b50d1fd3bb7fbfe3cc274f2bbdcb0c (diff)
Merge branch 'rust-lang:main' into codespaces
Diffstat (limited to 'exercises')
-rw-r--r--exercises/README.md9
-rw-r--r--exercises/conversions/as_ref_mut.rs13
-rw-r--r--exercises/enums/enums2.rs2
-rw-r--r--exercises/enums/enums3.rs3
-rw-r--r--exercises/error_handling/errors5.rs2
-rw-r--r--exercises/hashmaps/hashmaps3.rs2
-rw-r--r--exercises/intro/intro1.rs9
-rw-r--r--exercises/iterators/README.md8
-rw-r--r--exercises/iterators/iterators1.rs (renamed from exercises/standard_library_types/iterators1.rs)0
-rw-r--r--exercises/iterators/iterators2.rs (renamed from exercises/standard_library_types/iterators2.rs)0
-rw-r--r--exercises/iterators/iterators3.rs (renamed from exercises/standard_library_types/iterators3.rs)0
-rw-r--r--exercises/iterators/iterators4.rs (renamed from exercises/standard_library_types/iterators4.rs)0
-rw-r--r--exercises/iterators/iterators5.rs (renamed from exercises/standard_library_types/iterators5.rs)0
-rw-r--r--exercises/options/options1.rs2
-rw-r--r--exercises/options/options2.rs2
-rw-r--r--exercises/quiz2.rs4
-rw-r--r--exercises/smart_pointers/README.md11
-rw-r--r--exercises/smart_pointers/arc1.rs (renamed from exercises/standard_library_types/arc1.rs)2
-rw-r--r--exercises/smart_pointers/box1.rs (renamed from exercises/standard_library_types/box1.rs)0
-rw-r--r--exercises/smart_pointers/cow1.rs74
-rw-r--r--exercises/smart_pointers/rc1.rs (renamed from exercises/standard_library_types/rc1.rs)1
-rw-r--r--exercises/standard_library_types/README.md10
-rw-r--r--exercises/standard_library_types/cow1.rs48
-rw-r--r--exercises/threads/threads1.rs25
-rw-r--r--exercises/traits/traits1.rs4
-rw-r--r--exercises/traits/traits2.rs4
-rw-r--r--exercises/vecs/README.md2
27 files changed, 145 insertions, 92 deletions
diff --git a/exercises/README.md b/exercises/README.md
index e52137c..c7effa9 100644
--- a/exercises/README.md
+++ b/exercises/README.md
@@ -7,7 +7,7 @@
| if | §3.5 |
| primitive_types | §3.2, §4.3 |
| vecs | §8.1 |
-| move_semantics | §4.1, §4.2 |
+| move_semantics | §4.1-2 |
| structs | §5.1, §5.3 |
| enums | §6, §18.3 |
| strings | §8.2 |
@@ -19,8 +19,9 @@
| traits | §10.2 |
| tests | §11.1 |
| lifetimes | §10.3 |
-| standard_library_types | §13.2, §15.1, §16.3 |
-| threads | §16.1, §16.2, §16.3 |
+| iterators | §13.2-4 |
+| threads | §16.1-3 |
+| smart_pointers | §15, §16.3 |
| macros | §19.6 |
-| clippy | n/a |
+| clippy | §21.4 |
| conversions | n/a |
diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs
index c9eed7d..e6a9d11 100644
--- a/exercises/conversions/as_ref_mut.rs
+++ b/exercises/conversions/as_ref_mut.rs
@@ -5,21 +5,22 @@
// I AM NOT DONE
-// Obtain the number of bytes (not characters) in the given argument
-// Add the AsRef trait appropriately as a trait bound
+// Obtain the number of bytes (not characters) in the given argument.
+// TODO: Add the AsRef trait appropriately as a trait bound.
fn byte_counter<T>(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
+// Obtain the number of characters (not bytes) in the given argument.
+// TODO: Add the AsRef trait appropriately as a trait bound.
fn char_counter<T>(arg: T) -> usize {
arg.as_ref().chars().count()
}
-// Squares a number using as_mut(). Add the trait bound as is appropriate and
-// implement the function body.
+// Squares a number using as_mut().
+// TODO: Add the appropriate trait bound.
fn num_sq<T>(arg: &mut T) {
+ // TODO: Implement the function body.
???
}
diff --git a/exercises/enums/enums2.rs b/exercises/enums/enums2.rs
index 18479f8..167a6b2 100644
--- a/exercises/enums/enums2.rs
+++ b/exercises/enums/enums2.rs
@@ -10,7 +10,7 @@ enum Message {
impl Message {
fn call(&self) {
- println!("{:?}", &self);
+ println!("{:?}", self);
}
}
diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs
index 55acf6b..a2a9d58 100644
--- a/exercises/enums/enums3.rs
+++ b/exercises/enums/enums3.rs
@@ -38,6 +38,7 @@ impl State {
fn process(&mut self, message: Message) {
// TODO: create a match expression to process the different message variants
+ // Remember: When passing a tuple as a function argument, you'll need extra parentheses: fn function((t, u, p, l, e))
}
}
@@ -52,7 +53,7 @@ mod tests {
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
};
- state.process(Message::ChangeColor((255, 0, 255)));
+ state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("hello world")));
state.process(Message::Move(Point { x: 10, y: 15 }));
state.process(Message::Quit);
diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs
index 6da06ef..eb5506c 100644
--- a/exercises/error_handling/errors5.rs
+++ b/exercises/error_handling/errors5.rs
@@ -4,7 +4,7 @@
// 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.
-// For now, think of the `Box<dyn ...>` type as an "I want anything that does ???" type, which, given
+// For now, think of the `Box<dyn ???>` type as an "I want anything that does ???" type, which, given
// Rust's usual standards for runtime safety, should strike you as somewhat lenient!
// 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
diff --git a/exercises/hashmaps/hashmaps3.rs b/exercises/hashmaps/hashmaps3.rs
index 18dd44c..ad3baa6 100644
--- a/exercises/hashmaps/hashmaps3.rs
+++ b/exercises/hashmaps/hashmaps3.rs
@@ -37,7 +37,7 @@ fn build_scores_table(results: String) -> HashMap<String, Team> {
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
+ // will be the number of goals conceded from team_2, and similarly
// goals scored by team_2 will be the number of goals conceded by
// team_1.
}
diff --git a/exercises/intro/intro1.rs b/exercises/intro/intro1.rs
index 45c5acb..cfc55c3 100644
--- a/exercises/intro/intro1.rs
+++ b/exercises/intro/intro1.rs
@@ -26,5 +26,12 @@ fn main() {
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.");
+ println!(
+ "Going forward, the source of the exercises will always be in the success/failure output."
+ );
+ println!();
+ println!(
+ "If you want to use rust-analyzer, Rust's LSP implementation, make sure your editor is set"
+ );
+ println!("up, and then run `rustlings lsp` before continuing.")
}
diff --git a/exercises/iterators/README.md b/exercises/iterators/README.md
new file mode 100644
index 0000000..0e8b671
--- /dev/null
+++ b/exercises/iterators/README.md
@@ -0,0 +1,8 @@
+# Iterators
+
+This section will teach you about Iterators.
+
+## Further information
+
+- [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html)
+- [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/)
diff --git a/exercises/standard_library_types/iterators1.rs b/exercises/iterators/iterators1.rs
index 0379c6b..0379c6b 100644
--- a/exercises/standard_library_types/iterators1.rs
+++ b/exercises/iterators/iterators1.rs
diff --git a/exercises/standard_library_types/iterators2.rs b/exercises/iterators/iterators2.rs
index 29c53af..29c53af 100644
--- a/exercises/standard_library_types/iterators2.rs
+++ b/exercises/iterators/iterators2.rs
diff --git a/exercises/standard_library_types/iterators3.rs b/exercises/iterators/iterators3.rs
index c97a625..c97a625 100644
--- a/exercises/standard_library_types/iterators3.rs
+++ b/exercises/iterators/iterators3.rs
diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/iterators/iterators4.rs
index a02470e..a02470e 100644
--- a/exercises/standard_library_types/iterators4.rs
+++ b/exercises/iterators/iterators4.rs
diff --git a/exercises/standard_library_types/iterators5.rs b/exercises/iterators/iterators5.rs
index 0593d12..0593d12 100644
--- a/exercises/standard_library_types/iterators5.rs
+++ b/exercises/iterators/iterators5.rs
diff --git a/exercises/options/options1.rs b/exercises/options/options1.rs
index 1149af0..1f891b0 100644
--- a/exercises/options/options1.rs
+++ b/exercises/options/options1.rs
@@ -6,10 +6,10 @@
// 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 and 12AM is a value of 0
// The Option output should gracefully handle cases where time_of_day > 23.
+ // TODO: Complete the function body - remember to return an Option!
???
}
diff --git a/exercises/options/options2.rs b/exercises/options/options2.rs
index b112047..4e36443 100644
--- a/exercises/options/options2.rs
+++ b/exercises/options/options2.rs
@@ -5,8 +5,6 @@
#[cfg(test)]
mod tests {
- use super::*;
-
#[test]
fn simple_option() {
let target = "rustlings";
diff --git a/exercises/quiz2.rs b/exercises/quiz2.rs
index 606d3c7..5c42dae 100644
--- a/exercises/quiz2.rs
+++ b/exercises/quiz2.rs
@@ -6,7 +6,7 @@
// - Modules
// - Enums
-// Let's build a little machine in form of a function.
+// Let's build a little machine in the 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
@@ -42,7 +42,7 @@ mod my_module {
#[cfg(test)]
mod tests {
- // TODO: What do we have to import to have `transformer` in scope?
+ // TODO: What do we need to import to have `transformer` in scope?
use ???;
use super::Command;
diff --git a/exercises/smart_pointers/README.md b/exercises/smart_pointers/README.md
new file mode 100644
index 0000000..c517ae3
--- /dev/null
+++ b/exercises/smart_pointers/README.md
@@ -0,0 +1,11 @@
+# Smart Pointers
+In Rust, smart pointers are variables that contain an address in memory and reference some other data, but they also have additional metadata and capabilities.
+Smart pointers in Rust often own the data they point to, while references only borrow data.
+
+## Further Information
+
+- [Smart Pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html)
+- [Using Box to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html)
+- [Rc\<T\>, the Reference Counted Smart Pointer](https://doc.rust-lang.org/book/ch15-04-rc.html)
+- [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html)
+- [Cow Documentation](https://doc.rust-lang.org/std/borrow/enum.Cow.html)
diff --git a/exercises/standard_library_types/arc1.rs b/exercises/smart_pointers/arc1.rs
index 93a2703..ffb306a 100644
--- a/exercises/standard_library_types/arc1.rs
+++ b/exercises/smart_pointers/arc1.rs
@@ -32,7 +32,7 @@ fn main() {
for offset in 0..8 {
let child_numbers = // TODO
joinhandles.push(thread::spawn(move || {
- let sum: u32 = child_numbers.iter().filter(|n| *n % 8 == offset).sum();
+ let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum();
println!("Sum of offset {} is {}", offset, sum);
}));
}
diff --git a/exercises/standard_library_types/box1.rs b/exercises/smart_pointers/box1.rs
index 66cf00f..66cf00f 100644
--- a/exercises/standard_library_types/box1.rs
+++ b/exercises/smart_pointers/box1.rs
diff --git a/exercises/smart_pointers/cow1.rs b/exercises/smart_pointers/cow1.rs
new file mode 100644
index 0000000..885138a
--- /dev/null
+++ b/exercises/smart_pointers/cow1.rs
@@ -0,0 +1,74 @@
+// cow1.rs
+
+// This exercise explores the Cow, or Clone-On-Write type.
+// Cow is a clone-on-write smart pointer.
+// It can enclose and provide immutable access to borrowed data, and clone the data lazily when mutation or ownership is required.
+// The type is designed to work with general borrowed data via the Borrow trait.
+//
+// This exercise is meant to show you what to expect when passing data to Cow.
+// Fix the unit tests by checking for Cow::Owned(_) and Cow::Borrowed(_) at the TODO markers.
+
+// I AM NOT DONE
+
+use std::borrow::Cow;
+
+fn abs_all<'a, 'b>(input: &'a mut Cow<'b, [i32]>) -> &'a mut Cow<'b, [i32]> {
+ for i in 0..input.len() {
+ let v = input[i];
+ if v < 0 {
+ // Clones into a vector if not already owned.
+ input.to_mut()[i] = -v;
+ }
+ }
+ input
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn reference_mutation() -> Result<(), &'static str> {
+ // Clone occurs because `input` needs to be mutated.
+ let slice = [-1, 0, 1];
+ let mut input = Cow::from(&slice[..]);
+ match abs_all(&mut input) {
+ Cow::Owned(_) => Ok(()),
+ _ => Err("Expected owned value"),
+ }
+ }
+
+ #[test]
+ fn reference_no_mutation() -> Result<(), &'static str> {
+ // No clone occurs because `input` doesn't need to be mutated.
+ let slice = [0, 1, 2];
+ let mut input = Cow::from(&slice[..]);
+ match abs_all(&mut input) {
+ // TODO
+ }
+ }
+
+ #[test]
+ fn owned_no_mutation() -> Result<(), &'static str> {
+ // We can also pass `slice` without `&` so Cow owns it directly.
+ // In this case no mutation occurs and thus also no clone,
+ // but the result is still owned because it always was.
+ let slice = vec![0, 1, 2];
+ let mut input = Cow::from(slice);
+ match abs_all(&mut input) {
+ // TODO
+ }
+ }
+
+ #[test]
+ fn owned_mutation() -> Result<(), &'static str> {
+ // Of course this is also the case if a mutation does occur.
+ // In this case the call to `to_mut()` returns a reference to
+ // the same data as before.
+ let slice = vec![-1, 0, 1];
+ let mut input = Cow::from(slice);
+ match abs_all(&mut input) {
+ // TODO
+ }
+ }
+}
diff --git a/exercises/standard_library_types/rc1.rs b/exercises/smart_pointers/rc1.rs
index 9b907fd..d62f361 100644
--- a/exercises/standard_library_types/rc1.rs
+++ b/exercises/smart_pointers/rc1.rs
@@ -6,6 +6,7 @@
// Make this code compile by using the proper Rc primitives to express that the sun has multiple owners.
// I AM NOT DONE
+
use std::rc::Rc;
#[derive(Debug)]
diff --git a/exercises/standard_library_types/README.md b/exercises/standard_library_types/README.md
deleted file mode 100644
index 809d61f..0000000
--- a/exercises/standard_library_types/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Standard library types
-
-This section will teach you about Box, Shared-State Concurrency and Iterators.
-
-## Further information
-
-- [Using Box to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html)
-- [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html)
-- [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html)
-- [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/)
diff --git a/exercises/standard_library_types/cow1.rs b/exercises/standard_library_types/cow1.rs
deleted file mode 100644
index 5fba251..0000000
--- a/exercises/standard_library_types/cow1.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-// cow1.rs
-
-// This exercise explores the Cow, or Clone-On-Write type.
-// Cow is a clone-on-write smart pointer.
-// It can enclose and provide immutable access to borrowed data, and clone the data lazily when mutation or ownership is required.
-// The type is designed to work with general borrowed data via the Borrow trait.
-
-// I AM NOT DONE
-
-use std::borrow::Cow;
-
-fn abs_all<'a, 'b>(input: &'a mut Cow<'b, [i32]>) -> &'a mut Cow<'b, [i32]> {
- for i in 0..input.len() {
- let v = input[i];
- if v < 0 {
- // Clones into a vector if not already owned.
- input.to_mut()[i] = -v;
- }
- }
- input
-}
-
-fn main() {
- // No clone occurs because `input` doesn't need to be mutated.
- let slice = [0, 1, 2];
- let mut input = Cow::from(&slice[..]);
- match abs_all(&mut input) {
- Cow::Borrowed(_) => println!("I borrowed the slice!"),
- _ => panic!("expected borrowed value"),
- }
-
- // Clone occurs because `input` needs to be mutated.
- let slice = [-1, 0, 1];
- let mut input = Cow::from(&slice[..]);
- match abs_all(&mut input) {
- Cow::Owned(_) => println!("I modified the slice and now own it!"),
- _ => panic!("expected owned value"),
- }
-
- // No clone occurs because `input` is already owned.
- let slice = vec![-1, 0, 1];
- let mut input = Cow::from(slice);
- match abs_all(&mut input) {
- // TODO
- Cow::Borrowed(_) => println!("I own this slice!"),
- _ => panic!("expected borrowed value"),
- }
-}
diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs
index e59f4ce..d6376db 100644
--- a/exercises/threads/threads1.rs
+++ b/exercises/threads/threads1.rs
@@ -1,31 +1,38 @@
// threads1.rs
// 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.
+
+// This program spawns multiple threads that each run for at least 250ms,
+// and each thread returns how much time they took to complete.
+// The program should wait until all the spawned threads have finished and
+// should collect their return values into a vector.
// I AM NOT DONE
use std::thread;
-use std::time::Duration;
-
+use std::time::{Duration, Instant};
fn main() {
-
let mut handles = vec![];
for i in 0..10 {
- thread::spawn(move || {
+ handles.push(thread::spawn(move || {
+ let start = Instant::now();
thread::sleep(Duration::from_millis(250));
println!("thread {} is complete", i);
- });
+ start.elapsed().as_millis()
+ }));
}
- let mut completed_threads = 0;
+ let mut results: Vec<u128> = vec![];
for handle in handles {
// TODO: a struct is returned from thread::spawn, can you use it?
- completed_threads += 1;
}
- if completed_threads != 10 {
+ if results.len() != 10 {
panic!("Oh no! All the spawned threads did not finish!");
}
+ println!();
+ for (i, result) in results.into_iter().enumerate() {
+ println!("thread {} took {}ms", i, result);
+ }
}
diff --git a/exercises/traits/traits1.rs b/exercises/traits/traits1.rs
index 5b9d8d5..f5320a5 100644
--- a/exercises/traits/traits1.rs
+++ b/exercises/traits/traits1.rs
@@ -2,7 +2,7 @@
// Time to implement some traits!
//
// Your task is to implement the trait
-// `AppendBar' for the type `String'.
+// `AppendBar` for the type `String`.
//
// The trait AppendBar has only one function,
// which appends "Bar" to any object
@@ -16,7 +16,7 @@ trait AppendBar {
}
impl AppendBar for String {
- //Add your code here
+ // TODO: Implement `AppendBar` for type `String`.
}
fn main() {
diff --git a/exercises/traits/traits2.rs b/exercises/traits/traits2.rs
index 708bb19..288b498 100644
--- a/exercises/traits/traits2.rs
+++ b/exercises/traits/traits2.rs
@@ -1,7 +1,7 @@
// traits2.rs
//
// Your task is to implement the trait
-// `AppendBar' for a vector of strings.
+// `AppendBar` for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
@@ -17,7 +17,7 @@ trait AppendBar {
fn append_bar(self) -> Self;
}
-//TODO: Add your code here
+// TODO: Implement trait `AppendBar` for a vector of strings.
#[cfg(test)]
mod tests {
diff --git a/exercises/vecs/README.md b/exercises/vecs/README.md
index ebe90bf..8ff9b85 100644
--- a/exercises/vecs/README.md
+++ b/exercises/vecs/README.md
@@ -13,3 +13,5 @@ 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)
+- [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut)
+- [`map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map)