mirror of
https://github.com/rust-lang/rustlings.git
synced 2025-01-11 00:00:04 +03:00
Compare commits
9 commits
532c9ebb30
...
d768353806
Author | SHA1 | Date | |
---|---|---|---|
d768353806 | |||
e4dbbbf5f5 | |||
fd558065c7 | |||
68142aff7f | |||
946c29679e | |||
6a79ada7f2 | |||
835ec72622 | |||
a9f0c7bf1f | |||
0abcdeed42 |
|
@ -1,21 +1,17 @@
|
||||||
// Use a tuple index to access the second element of `numbers`. You can put the
|
|
||||||
// expression for the second element where ??? is so that the test passes.
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// You can optionally experiment here.
|
// You can optionally experiment here.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn indexing_tuple() {
|
fn indexing_tuple() {
|
||||||
let numbers = (1, 2, 3);
|
let numbers = (1, 2, 3);
|
||||||
// Replace below ??? with the tuple indexing syntax.
|
|
||||||
let second = ???;
|
|
||||||
|
|
||||||
assert_eq!(2, second,
|
// TODO: Use a tuple index to access the second element of `numbers`
|
||||||
"This is not the 2nd number in the tuple!")
|
// and assign it to a variable called `second`.
|
||||||
|
// let second = ???;
|
||||||
|
|
||||||
|
assert_eq!(second, 2, "This is not the 2nd number in the tuple!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
// Your task is to create a `Vec` which holds the exact same elements as in the
|
|
||||||
// array `a`.
|
|
||||||
//
|
|
||||||
// Make me compile and pass the test!
|
|
||||||
|
|
||||||
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
|
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
|
||||||
let a = [10, 20, 30, 40]; // a plain array
|
let a = [10, 20, 30, 40]; // Array
|
||||||
let v = // TODO: declare your vector here with the macro for vectors
|
|
||||||
|
// TODO: Create a vector called `v` which contains the exact same elements as in the array `a`.
|
||||||
|
// Use the vector macro.
|
||||||
|
// let v = ???;
|
||||||
|
|
||||||
(a, v)
|
(a, v)
|
||||||
}
|
}
|
||||||
|
@ -21,6 +19,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_array_and_vec_similarity() {
|
fn test_array_and_vec_similarity() {
|
||||||
let (a, v) = array_and_vec();
|
let (a, v) = array_and_vec();
|
||||||
assert_eq!(a, v[..]);
|
assert_eq!(a, *v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
// A Vec of even numbers is given. Your task is to complete the loop so that
|
fn vec_loop(input: &[i32]) -> Vec<i32> {
|
||||||
// each number in the Vec is multiplied by 2.
|
let mut output = Vec::new();
|
||||||
//
|
|
||||||
// Make me pass the test!
|
|
||||||
|
|
||||||
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
|
for element in input {
|
||||||
for element in v.iter_mut() {
|
// TODO: Multiply each element in the `input` slice by 2 and push it to
|
||||||
// TODO: Fill this up so that each element in the Vec `v` is
|
// the `output` vector.
|
||||||
// multiplied by 2.
|
|
||||||
???
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, `v` should be equal to [4, 8, 12, 16, 20].
|
output
|
||||||
v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vec_map(v: &Vec<i32>) -> Vec<i32> {
|
fn vec_map_example(input: &[i32]) -> Vec<i32> {
|
||||||
v.iter().map(|element| {
|
// An example of collecting a vector after mapping.
|
||||||
// TODO: Do the same thing as above - but instead of mutating the
|
// We map each element of the `input` slice to its value plus 1.
|
||||||
// Vec, you can just return the new number!
|
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
|
||||||
???
|
input.iter().map(|element| element + 1).collect()
|
||||||
}).collect()
|
}
|
||||||
|
|
||||||
|
fn vec_map(input: &[i32]) -> Vec<i32> {
|
||||||
|
// TODO: Here, we also want to multiply each element in the `input` slice
|
||||||
|
// by 2, but with iterator mapping instead of manually pushing into an empty
|
||||||
|
// vector.
|
||||||
|
// See the example in the function `vec_map_example` above.
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.map(|element| {
|
||||||
|
// ???
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -32,17 +39,22 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vec_loop() {
|
fn test_vec_loop() {
|
||||||
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
|
let input = [2, 4, 6, 8, 10];
|
||||||
let ans = vec_loop(v.clone());
|
let ans = vec_loop(&input);
|
||||||
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
|
#[test]
|
||||||
|
fn test_vec_map_example() {
|
||||||
|
let input = [1, 2, 3];
|
||||||
|
let ans = vec_map_example(&input);
|
||||||
|
assert_eq!(ans, [2, 3, 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vec_map() {
|
fn test_vec_map() {
|
||||||
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
|
let input = [2, 4, 6, 8, 10];
|
||||||
let ans = vec_map(&v);
|
let ans = vec_map(&input);
|
||||||
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// TODO: Fix the compiler error in this function.
|
||||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||||
let vec = vec;
|
let vec = vec;
|
||||||
|
|
||||||
|
@ -17,9 +18,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn move_semantics1() {
|
fn move_semantics1() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
let vec1 = fill_vec(vec0);
|
let vec1 = fill_vec(vec0);
|
||||||
|
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// Make the test pass by finding a way to keep both Vecs separate!
|
|
||||||
|
|
||||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||||
let mut vec = vec;
|
let mut vec = vec;
|
||||||
|
|
||||||
|
@ -16,13 +14,15 @@ fn main() {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
// TODO: Make both vectors `vec0` and `vec1` accessible at the same time to
|
||||||
|
// fix the compiler error in the test.
|
||||||
#[test]
|
#[test]
|
||||||
fn move_semantics2() {
|
fn move_semantics2() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
let vec1 = fill_vec(vec0);
|
let vec1 = fill_vec(vec0);
|
||||||
|
|
||||||
assert_eq!(vec0, vec![22, 44, 66]);
|
assert_eq!(vec0, [22, 44, 66]);
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
assert_eq!(vec1, [22, 44, 66, 88]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// Make me compile without adding new lines -- just changing existing lines! (no
|
// TODO: Fix the compiler error in the function without adding any new line.
|
||||||
// lines with multiple semicolons necessary!)
|
|
||||||
|
|
||||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||||
vec.push(88);
|
vec.push(88);
|
||||||
|
|
||||||
|
@ -18,9 +16,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn move_semantics3() {
|
fn move_semantics3() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
let vec1 = fill_vec(vec0);
|
let vec1 = fill_vec(vec0);
|
||||||
|
assert_eq!(vec1, [22, 44, 66, 88]);
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,18 @@
|
||||||
// Refactor this code so that instead of passing `vec0` into the `fill_vec`
|
|
||||||
// function, the Vector gets created in the function itself and passed back to
|
|
||||||
// the test function.
|
|
||||||
|
|
||||||
// `fill_vec()` no longer takes `vec: Vec<i32>` as argument - don't change this!
|
|
||||||
fn fill_vec() -> Vec<i32> {
|
|
||||||
// Instead, let's create and fill the Vec in here - how do you do that?
|
|
||||||
let mut vec = vec;
|
|
||||||
|
|
||||||
vec.push(88);
|
|
||||||
|
|
||||||
vec
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// You can optionally experiment here.
|
// You can optionally experiment here.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
// TODO: Fix the compiler errors only by reordering the lines in the test.
|
||||||
|
// Don't add, change or remove any line.
|
||||||
#[test]
|
#[test]
|
||||||
fn move_semantics4() {
|
fn move_semantics5() {
|
||||||
let vec0 = vec![22, 44, 66];
|
let mut x = 100;
|
||||||
|
let y = &mut x;
|
||||||
let vec1 = fill_vec(vec0);
|
let z = &mut x;
|
||||||
|
*y += 100;
|
||||||
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
*z += 1000;
|
||||||
|
assert_eq!(x, 1200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
// Make me compile only by reordering the lines in the test, but without adding,
|
// TODO: Fix the compiler errors without changing anything except adding or
|
||||||
// changing or removing any of them.
|
// removing references (the character `&`).
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// You can optionally experiment here.
|
let data = "Rust is great!".to_string();
|
||||||
|
|
||||||
|
get_char(data);
|
||||||
|
|
||||||
|
string_uppercase(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
// Shouldn't take ownership
|
||||||
mod tests {
|
fn get_char(data: String) -> char {
|
||||||
use super::*;
|
data.chars().last().unwrap()
|
||||||
|
}
|
||||||
#[test]
|
|
||||||
fn move_semantics5() {
|
// Should take ownership
|
||||||
let mut x = 100;
|
fn string_uppercase(mut data: &String) {
|
||||||
let y = &mut x;
|
data = &data.to_uppercase();
|
||||||
let z = &mut x;
|
|
||||||
*y += 100;
|
println!("{data}");
|
||||||
*z += 1000;
|
|
||||||
assert_eq!(x, 1200);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
// You can't change anything except adding or removing references.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let data = "Rust is great!".to_string();
|
|
||||||
|
|
||||||
get_char(data);
|
|
||||||
|
|
||||||
string_uppercase(&data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should not take ownership
|
|
||||||
fn get_char(data: String) -> char {
|
|
||||||
data.chars().last().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should take ownership
|
|
||||||
fn string_uppercase(mut data: &String) {
|
|
||||||
data = &data.to_uppercase();
|
|
||||||
|
|
||||||
println!("{}", data);
|
|
||||||
}
|
|
|
@ -296,7 +296,7 @@ While you could use a destructuring `let` for the tuple here, try
|
||||||
indexing into it instead, as explained in the last example of the
|
indexing into it instead, as explained in the last example of the
|
||||||
'Data Types -> The Tuple Type' section of the book:
|
'Data Types -> The Tuple Type' section of the book:
|
||||||
https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
|
https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
|
||||||
Now you have another tool in your toolbox!"""
|
Now, you have another tool in your toolbox!"""
|
||||||
|
|
||||||
# VECS
|
# VECS
|
||||||
|
|
||||||
|
@ -307,8 +307,9 @@ hint = """
|
||||||
In Rust, there are two ways to define a Vector.
|
In Rust, there are two ways to define a Vector.
|
||||||
1. One way is to use the `Vec::new()` function to create a new vector
|
1. One way is to use the `Vec::new()` function to create a new vector
|
||||||
and fill it with the `push()` method.
|
and fill it with the `push()` method.
|
||||||
2. The second way, which is simpler is to use the `vec![]` macro and
|
2. The second way is to use the `vec![]` macro and define your elements
|
||||||
define your elements inside the square brackets.
|
inside the square brackets. This way is simpler when you exactly know
|
||||||
|
the initial values.
|
||||||
|
|
||||||
Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html
|
Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html
|
||||||
of the Rust book to learn more.
|
of the Rust book to learn more.
|
||||||
|
@ -318,15 +319,10 @@ of the Rust book to learn more.
|
||||||
name = "vecs2"
|
name = "vecs2"
|
||||||
dir = "05_vecs"
|
dir = "05_vecs"
|
||||||
hint = """
|
hint = """
|
||||||
In the first function we are looping over the Vector and getting a reference to
|
In the first function, we create an empty vector and want to push new elements
|
||||||
one `element` at a time.
|
to it.
|
||||||
|
|
||||||
To modify the value of that `element` we need to use the `*` dereference
|
In the second function, we map the values of the input and collect them into a vector.
|
||||||
operator. You can learn more in this chapter of the Rust book:
|
|
||||||
https://doc.rust-lang.org/stable/book/ch08-01-vectors.html#iterating-over-the-values-in-a-vector
|
|
||||||
|
|
||||||
In the second function this dereferencing is not necessary, because the `map`
|
|
||||||
function expects the new value to be returned.
|
|
||||||
|
|
||||||
After you've completed both functions, decide for yourself which approach you
|
After you've completed both functions, decide for yourself which approach you
|
||||||
like better.
|
like better.
|
||||||
|
@ -346,8 +342,7 @@ error on the line where we push an element to the vector, right?
|
||||||
The fix for this is going to be adding one keyword, and the addition is NOT on
|
The fix for this is going to be adding one keyword, and the addition is NOT on
|
||||||
the line where we push to the vector (where the error is).
|
the line where we push to the vector (where the error is).
|
||||||
|
|
||||||
Also: Try accessing `vec0` after having called `fill_vec()`. See what
|
Try accessing `vec0` after having called `fill_vec()`. See what happens!"""
|
||||||
happens!"""
|
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
name = "move_semantics2"
|
name = "move_semantics2"
|
||||||
|
@ -357,16 +352,10 @@ When running this exercise for the first time, you'll notice an error about
|
||||||
"borrow of moved value". In Rust, when an argument is passed to a function and
|
"borrow of moved value". In Rust, when an argument is passed to a function and
|
||||||
it's not explicitly returned, you can't use the original variable anymore.
|
it's not explicitly returned, you can't use the original variable anymore.
|
||||||
We call this "moving" a variable. When we pass `vec0` into `fill_vec`, it's
|
We call this "moving" a variable. When we pass `vec0` into `fill_vec`, it's
|
||||||
being "moved" into `vec1`, meaning we can't access `vec0` anymore after the
|
being "moved" into `vec1`, meaning we can't access `vec0` anymore.
|
||||||
fact.
|
|
||||||
|
|
||||||
Rust provides a couple of different ways to mitigate this issue, feel free to
|
You could make another, separate version of the data that's in `vec0` and
|
||||||
try them all:
|
pass it to `fill_vec` instead.
|
||||||
1. You could make another, separate version of the data that's in `vec0` and
|
|
||||||
pass that to `fill_vec` instead.
|
|
||||||
2. Make `fill_vec` borrow its argument instead of taking ownership of it,
|
|
||||||
and then copy the data within the function (`vec.clone()`) in order to
|
|
||||||
return an owned `Vec<i32>`.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
|
@ -382,28 +371,15 @@ an existing binding to be a mutable binding instead of an immutable one :)"""
|
||||||
name = "move_semantics4"
|
name = "move_semantics4"
|
||||||
dir = "06_move_semantics"
|
dir = "06_move_semantics"
|
||||||
hint = """
|
hint = """
|
||||||
Stop reading whenever you feel like you have enough direction :) Or try
|
|
||||||
doing one step and then fixing the compiler errors that result!
|
|
||||||
So the end goal is to:
|
|
||||||
- get rid of the first line in main that creates the new vector
|
|
||||||
- so then `vec0` doesn't exist, so we can't pass it to `fill_vec`
|
|
||||||
- `fill_vec` has had its signature changed, which our call should reflect
|
|
||||||
- since we're not creating a new vec in `main` anymore, we need to create
|
|
||||||
a new vec in `fill_vec`, and fill it with the expected values"""
|
|
||||||
|
|
||||||
[[exercises]]
|
|
||||||
name = "move_semantics5"
|
|
||||||
dir = "06_move_semantics"
|
|
||||||
hint = """
|
|
||||||
Carefully reason about the range in which each mutable reference is in
|
Carefully reason about the range in which each mutable reference is in
|
||||||
scope. Does it help to update the value of referent (`x`) immediately after
|
scope. Does it help to update the value of referent (`x`) immediately after
|
||||||
the mutable reference is taken? Read more about 'Mutable References'
|
the mutable reference is taken?
|
||||||
in the book's section 'References and Borrowing':
|
Read more about 'Mutable References' in the book's section 'References and Borrowing':
|
||||||
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references.
|
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
name = "move_semantics6"
|
name = "move_semantics5"
|
||||||
dir = "06_move_semantics"
|
dir = "06_move_semantics"
|
||||||
test = false
|
test = false
|
||||||
hint = """
|
hint = """
|
||||||
|
@ -412,14 +388,10 @@ https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html
|
||||||
|
|
||||||
The first problem is that `get_char` is taking ownership of the string. So
|
The first problem is that `get_char` is taking ownership of the string. So
|
||||||
`data` is moved and can't be used for `string_uppercase`. `data` is moved to
|
`data` is moved and can't be used for `string_uppercase`. `data` is moved to
|
||||||
`get_char` first, meaning that `string_uppercase` cannot manipulate the data.
|
`get_char` first, meaning that `string_uppercase` can't manipulate the data.
|
||||||
|
|
||||||
Once you've fixed that, `string_uppercase`'s function signature will also need
|
Once you've fixed that, `string_uppercase`'s function signature will also need
|
||||||
to be adjusted.
|
to be adjusted."""
|
||||||
|
|
||||||
Can you figure out how?
|
|
||||||
|
|
||||||
Another hint: it has to do with the `&` character."""
|
|
||||||
|
|
||||||
# STRUCTS
|
# STRUCTS
|
||||||
|
|
||||||
|
|
|
@ -1 +1,16 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn indexing_tuple() {
|
||||||
|
let numbers = (1, 2, 3);
|
||||||
|
|
||||||
|
// Tuple indexing syntax.
|
||||||
|
let second = numbers.1;
|
||||||
|
|
||||||
|
assert_eq!(second, 2, "This is not the 2nd number in the tuple!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,23 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
|
||||||
|
let a = [10, 20, 30, 40]; // Array
|
||||||
|
|
||||||
|
// Used the `vec!` macro.
|
||||||
|
let v = vec![10, 20, 30, 40];
|
||||||
|
|
||||||
|
(a, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_array_and_vec_similarity() {
|
||||||
|
let (a, v) = array_and_vec();
|
||||||
|
assert_eq!(a, *v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,55 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn vec_loop(input: &[i32]) -> Vec<i32> {
|
||||||
|
let mut output = Vec::new();
|
||||||
|
|
||||||
|
for element in input {
|
||||||
|
output.push(2 * element);
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vec_map_example(input: &[i32]) -> Vec<i32> {
|
||||||
|
// An example of collecting a vector after mapping.
|
||||||
|
// We map each element of the `input` slice to its value plus 1.
|
||||||
|
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
|
||||||
|
input.iter().map(|element| element + 1).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vec_map(input: &[i32]) -> Vec<i32> {
|
||||||
|
// We will dive deeper into iterators, but for now, this is all what you
|
||||||
|
// had to do!
|
||||||
|
// Advanced note: This method is more efficient because it automatically
|
||||||
|
// preallocates enough capacity. This can be done manually in `vec_loop`
|
||||||
|
// using `Vec::with_capacity(input.len())` instead of `Vec::new()`.
|
||||||
|
input.iter().map(|element| 2 * element).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_loop() {
|
||||||
|
let input = [2, 4, 6, 8, 10];
|
||||||
|
let ans = vec_loop(&input);
|
||||||
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_map_example() {
|
||||||
|
let input = [1, 2, 3];
|
||||||
|
let ans = vec_map_example(&input);
|
||||||
|
assert_eq!(ans, [2, 3, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_map() {
|
||||||
|
let input = [2, 4, 6, 8, 10];
|
||||||
|
let ans = vec_map(&input);
|
||||||
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,25 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||||
|
let mut vec = vec;
|
||||||
|
// ^^^ added
|
||||||
|
|
||||||
|
vec.push(88);
|
||||||
|
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn move_semantics1() {
|
||||||
|
let vec0 = vec![22, 44, 66];
|
||||||
|
let vec1 = fill_vec(vec0);
|
||||||
|
// `vec0` can't be accessed anymore because it is moved to `fill_vec`.
|
||||||
|
assert_eq!(vec1, vec![22, 44, 66, 88]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,28 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||||
|
let mut vec = vec;
|
||||||
|
|
||||||
|
vec.push(88);
|
||||||
|
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn move_semantics2() {
|
||||||
|
let vec0 = vec![22, 44, 66];
|
||||||
|
|
||||||
|
// Cloning `vec0` so that the clone is moved into `fill_vec`, not `vec0`
|
||||||
|
// itself.
|
||||||
|
let vec1 = fill_vec(vec0.clone());
|
||||||
|
|
||||||
|
assert_eq!(vec0, [22, 44, 66]);
|
||||||
|
assert_eq!(vec1, [22, 44, 66, 88]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,22 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
|
||||||
|
// ^^^ added
|
||||||
|
vec.push(88);
|
||||||
|
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn move_semantics3() {
|
||||||
|
let vec0 = vec![22, 44, 66];
|
||||||
|
let vec1 = fill_vec(vec0);
|
||||||
|
assert_eq!(vec1, [22, 44, 66, 88]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,21 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn main() {
|
||||||
|
// You can optionally experiment here.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
// TODO: Fix the compiler errors only by reordering the lines in the test.
|
||||||
|
// Don't add, change or remove any line.
|
||||||
|
#[test]
|
||||||
|
fn move_semantics5() {
|
||||||
|
let mut x = 100;
|
||||||
|
let y = &mut x;
|
||||||
|
// `y` used here.
|
||||||
|
*y += 100;
|
||||||
|
// The mutable reference `y` is not used anymore,
|
||||||
|
// therefore a new reference can be created.
|
||||||
|
let z = &mut x;
|
||||||
|
*z += 1000;
|
||||||
|
assert_eq!(x, 1200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,21 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
fn main() {
|
||||||
|
let data = "Rust is great!".to_string();
|
||||||
|
|
||||||
|
get_char(&data);
|
||||||
|
|
||||||
|
string_uppercase(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrows instead of taking ownership.
|
||||||
|
// It is recommended to use `&str` instead of `&String` here. But this is
|
||||||
|
// enough for now because we didn't handle strings yet.
|
||||||
|
fn get_char(data: &String) -> char {
|
||||||
|
data.chars().last().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes ownership instead of borrowing.
|
||||||
|
fn string_uppercase(mut data: String) {
|
||||||
|
data = data.to_uppercase();
|
||||||
|
|
||||||
|
println!("{data}");
|
||||||
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
|
Loading…
Reference in a new issue