Vector Operations in Rust
This challenge focuses on implementing common vector operations in Rust using the Vec data structure. Understanding how to manipulate vectors efficiently is fundamental to many Rust programs, and this exercise will solidify your grasp of Rust's ownership and borrowing system while working with a core data structure. You'll be creating functions that perform transformations and filtering on vectors.
Problem Description
You are tasked with creating a module named vector_operations that provides several utility functions for working with vectors of integers (Vec<i32>). The module should include the following functions:
sum(vec: &Vec<i32>) -> i32: Calculates the sum of all elements in the input vector.average(vec: &Vec<i32>) -> f64: Calculates the average of all elements in the input vector. Return 0.0 if the vector is empty.filter_even(vec: &Vec<i32>) -> Vec<i32>: Creates a new vector containing only the even numbers from the input vector.map_squared(vec: &Vec<i32>) -> Vec<i32>: Creates a new vector where each element is the square of the corresponding element in the input vector.find_max(vec: &Vec<i32>) -> Option<i32>: Finds the maximum value in the input vector. ReturnsNoneif the vector is empty.
Key Requirements:
- The functions should take a reference to a
Vec<i32>as input to avoid unnecessary copying. - The functions should return a new
Vec<i32>when appropriate (e.g.,filter_even,map_squared). - Handle edge cases gracefully, such as empty vectors.
- Use idiomatic Rust code.
- The
vector_operationsmodule should be well-documented.
Expected Behavior:
The functions should behave as described above, producing the correct results for various inputs, including edge cases. The code should be clean, readable, and efficient.
Examples
Example 1:
Input: vec = [1, 2, 3, 4, 5]
Output: sum(vec) -> 15
Explanation: 1 + 2 + 3 + 4 + 5 = 15
Example 2:
Input: vec = [2, 4, 6, 8]
Output: filter_even(vec) -> [2, 4, 6, 8]
Explanation: All elements are even, so the filtered vector is the same.
Example 3:
Input: vec = [1, 3, 5, 7]
Output: filter_even(vec) -> []
Explanation: No elements are even, so the filtered vector is empty.
Example 4:
Input: vec = [1, 2, 3]
Output: map_squared(vec) -> [1, 4, 9]
Explanation: Each element is squared: 1*1 = 1, 2*2 = 4, 3*3 = 9
Example 5:
Input: vec = []
Output: average(vec) -> 0.0
Explanation: The vector is empty, so the average is 0.0.
Example 6:
Input: vec = [-5, -2, 0, 3, 8]
Output: find_max(vec) -> Some(8)
Explanation: 8 is the largest element in the vector.
Constraints
- The input vectors will contain only integers (
i32). - The size of the input vectors can vary, but should not exceed 10,000 elements. This is to prevent excessive memory usage during testing.
- The functions should execute in O(n) time complexity, where n is the number of elements in the vector, for all operations except
find_maxwhich can be O(n) as well. - The functions should not modify the original input vector.
Notes
- Consider using iterators for efficient processing of the vectors.
- The
Option<i32>type is used to handle the case where the input vector is empty forfind_max. - Pay close attention to Rust's ownership and borrowing rules when working with vectors. Using references (
&Vec<i32>) is crucial to avoid unnecessary copying and potential ownership issues. - Think about how to handle potential panics or errors gracefully. In this case, returning
Optionor a default value is preferred over panicking.