Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "collections" exercises #572

Merged
merged 2 commits into from
Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions exercises/collections/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
### Collections

Rust’s standard library includes a number of very useful data
structures called collections. Most other data types represent one
specific value, but collections can contain multiple values. Unlike
the built-in array and tuple types, the data these collections point
to is stored on the heap, which means the amount of data does not need
to be known at compile time and can grow or shrink as the program
runs.

This exercise will get you familiar with two fundamental data
structures that are used very often in Rust programs:

* A *vector* allows you to store a variable number of values next to
each other.
* A *hash map* allows you to associate a value with a particular key.
You may also know this by the names *map* in C++, *dictionary* in
Python or an *associative array* in other languages.

[Rust book chapter](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html)
46 changes: 46 additions & 0 deletions exercises/collections/hashmap1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// hashmap1.rs
// A basket of fruits in the form of a hash map needs to be defined.
// The key represents the name of the fruit and the value represents
// how many of that particular fruit is in the basket. You have to put
// at least three different types of fruits (e.g apple, banana, mango)
// in the basket and the total count of all the fruits should be at
// least five.
//
// Make me compile and pass the tests!
//
// Execute the command `rustlings hint collections3` if you need
// hints.

// I AM NOT DONE

use std::collections::HashMap;

fn fruit_basket() -> HashMap<String, u32> {
let mut basket = // TODO: declare your hash map here.

// Two bananas are already given for you :)
basket.insert(String::from("banana"), 2);

// TODO: Put more fruits in your basket here.

basket
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn at_least_three_types_of_fruits() {
let basket = fruit_basket();
assert!(basket.len() >= 3);
}

#[test]
fn at_least_five_fruits() {
let basket = fruit_basket();
assert!(basket
sazid marked this conversation as resolved.
Show resolved Hide resolved
.values()
.sum::<u32>() >= 5);
}
}
83 changes: 83 additions & 0 deletions exercises/collections/hashmap2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// hashmap2.rs

// A basket of fruits in the form of a hash map is given. The key
// represents the name of the fruit and the value represents how many
// of that particular fruit is in the basket. You have to put *MORE
// THAN 11* fruits in the basket. Three types of fruits - Apple (4),
// Mango (2) and Lichi (5) are already given in the basket. You are
// not allowed to insert any more of these fruits!
//
// Make me pass the tests!
//
// Execute the command `rustlings hint collections4` if you need
// hints.

// I AM NOT DONE

use std::collections::HashMap;

#[derive(Hash, PartialEq, Eq)]
enum Fruit {
Apple,
Banana,
Mango,
Lichi,
Pineapple,
}

fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
let fruit_kinds = vec![
Fruit::Apple,
Fruit::Banana,
Fruit::Mango,
Fruit::Lichi,
Fruit::Pineapple,
];

for fruit in fruit_kinds {
// TODO: Put new fruits if not already present. Note that you
// are not allowed to put any type of fruit that's already
// present!
}
}

#[cfg(test)]
mod tests {
use super::*;

fn get_fruit_basket() -> HashMap<Fruit, u32> {
let mut basket = HashMap::<Fruit, u32>::new();
basket.insert(Fruit::Apple, 4);
basket.insert(Fruit::Mango, 2);
basket.insert(Fruit::Lichi, 5);

basket
}

#[test]
fn test_given_fruits_are_not_modified() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4);
assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2);
assert_eq!(*basket.get(&Fruit::Lichi).unwrap(), 5);
}

#[test]
fn at_least_five_types_of_fruits() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
let count_fruit_kinds = basket.len();
assert!(count_fruit_kinds == 5);
}

#[test]
fn greater_than_eleven_fruits() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
let count = basket
sazid marked this conversation as resolved.
Show resolved Hide resolved
.values()
.sum::<u32>();
assert!(count > 11);
}
}
25 changes: 25 additions & 0 deletions exercises/collections/vec1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// vec1.rs
// 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!
// Execute the command `rustlings hint collections1` if you need hints.

// I AM NOT DONE

fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // a plain array
let v = // TODO: declare your vector here with the macro for vectors

(a, v)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert!(a.iter().zip(v.iter()).all(|(x, y)| x == y));
}
}
38 changes: 38 additions & 0 deletions exercises/collections/vec2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// vec2.rs
// A Vec of even numbers is given. Your task is to complete the loop
// so that each number in the Vec is multiplied by 2.
//
// Make me pass the test!
//
// Execute the command `rustlings hint collections2` if you need
// hints.

// I AM NOT DONE

fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for i in v.iter_mut() {
// TODO: Fill this up so that each element in the Vec `v` is
// multiplied by 2.
}

// At this point, `v` should be equal to [4, 8, 12, 16, 20].
v
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_vec_loop() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_loop(v.clone());

assert_eq!(
ans,
v.iter()
.map(|x| x * 2)
.collect::<Vec<i32>>()
);
}
}
52 changes: 52 additions & 0 deletions info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,58 @@ its internal structure (the `fruits` and `veggies` modules and
associated constants). It's almost there except for one keyword missing for
each constant."""

# COLLECTIONS

[[exercises]]
name = "collections1"
path = "exercises/collections/vec1.rs"
mode = "test"
hint = """
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
and fill it with the `push()` method.

2. The second way, which is simpler is to use the `vec![]` macro and
define your elements inside the square brackets.

Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html
of the Rust book to learn more.
"""

[[exercises]]
name = "collections2"
path = "exercises/collections/vec2.rs"
mode = "test"
hint = """
Hint 1: `i` is each element from the Vec as they are being iterated.
Can you try multiplying this?

Hint 2: Check the suggestion from the compiler error ;)
"""

[[exercises]]
name = "collections3"
path = "exercises/collections/hashmap1.rs"
mode = "test"
hint = """
Hint 1: Take a look at the return type of the function to figure out
the type for the `basket`.

Hint 2: Number of fruits should be at least 5. And you have to put
at least three different types of fruits.
"""

[[exercises]]
name = "collections4"
path = "exercises/collections/hashmap2.rs"
mode = "test"
hint = """
Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this.

Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
"""

# MACROS

[[exercises]]
Expand Down