Hone logo
Hone
Problems

Rust Vec Basics: Building a Dynamic Array

This challenge will test your understanding of Rust's Vec type, the standard library's dynamic array implementation. You will create a simple data structure that mimics some of Vec's core functionalities, allowing you to store and manipulate a collection of elements that can grow. This is a fundamental building block for many data-intensive applications.

Problem Description

Your task is to implement a struct named MyVec<T> that acts as a simplified version of std::vec::Vec<T>. This MyVec should be able to store elements of any type T. You need to implement the following core functionalities:

  • Initialization: Create an empty MyVec.
  • Adding Elements: Append new elements to the end of the MyVec.
  • Accessing Elements: Retrieve elements by their index.
  • Getting Length: Determine the number of elements currently stored.
  • Removing Elements: Remove the last element from the MyVec.

Key Requirements:

  1. MyVec<T> struct: Define a struct MyVec<T> that encapsulates the data. Internally, it should use a standard Rust Vec to manage the underlying storage.
  2. new() function: Implement an associated function new() that returns an empty MyVec<T>.
  3. push(value: T) method: Implement a method push that takes a value of type T and adds it to the end of the MyVec.
  4. get(index: usize) -> Option<&T> method: Implement a method get that takes an index and returns a reference to the element at that index wrapped in Option. If the index is out of bounds, it should return None.
  5. len() method: Implement a method len that returns the current number of elements in the MyVec as a usize.
  6. pop() -> Option<T> method: Implement a method pop that removes and returns the last element from the MyVec wrapped in Option. If the MyVec is empty, it should return None.

Expected Behavior:

  • When new() is called, an empty MyVec should be created with a length of 0.
  • push() should increase the length of the MyVec and store the provided value.
  • get() should correctly return a reference to the element at the specified index, or None for invalid indices.
  • len() should accurately report the number of elements.
  • pop() should remove and return the last element, decreasing the length, or return None if empty.

Edge Cases to Consider:

  • Accessing an index out of bounds with get().
  • Calling pop() on an empty MyVec.
  • Storing different types of data (e.g., integers, strings, custom structs).

Examples

Example 1:

let mut my_vec: MyVec<i32> = MyVec::new();
my_vec.push(10);
my_vec.push(20);
my_vec.push(30);

println!("Length: {}", my_vec.len()); // Expected: Length: 3
println!("Element at index 1: {:?}", my_vec.get(1)); // Expected: Element at index 1: Some(20)

Explanation: We create a new MyVec for integers, push three values, and then check its length and retrieve an element by its index.

Example 2:

let mut my_vec: MyVec<String> = MyVec::new();
my_vec.push("hello".to_string());
my_vec.push("world".to_string());

println!("Length before pop: {}", my_vec.len()); // Expected: Length before pop: 2
println!("Popped element: {:?}", my_vec.pop()); // Expected: Popped element: Some("world")
println!("Length after pop: {}", my_vec.len()); // Expected: Length after pop: 1
println!("Element at index 0: {:?}", my_vec.get(0)); // Expected: Element at index 0: Some("hello")
println!("Element at index 1: {:?}", my_vec.get(1)); // Expected: Element at index 1: None

Explanation: We demonstrate pushing strings, checking the length, popping the last element, and verifying the updated length and element accessibility.

Example 3: Edge Cases

let mut my_vec: MyVec<f64> = MyVec::new();

println!("Initial length: {}", my_vec.len()); // Expected: Initial length: 0
println!("Pop from empty: {:?}", my_vec.pop()); // Expected: Pop from empty: None
println!("Get at index 0: {:?}", my_vec.get(0)); // Expected: Get at index 0: None

my_vec.push(3.14);
println!("Get at index 1: {:?}", my_vec.get(1)); // Expected: Get at index 1: None

Explanation: This example covers the behavior when operating on an empty MyVec and attempting to access an out-of-bounds index after adding an element.

Constraints

  • Your MyVec<T> struct must use std::vec::Vec<T> internally for storage.
  • The get method must return Option<&T>.
  • The pop method must return Option<T>.
  • All methods should be implemented within an impl<T> MyVec<T> { ... } block.
  • No external crates are allowed, only the Rust standard library.

Notes

  • Remember to derive Debug for MyVec if you want to print it directly for debugging purposes (though the examples focus on specific method outputs).
  • Consider how Option is used to handle cases where an element might not exist or a operation might fail (like popping from an empty vector).
  • This exercise is about understanding composition and implementing simple interfaces. You are wrapping std::vec::Vec, not reimplementing its memory management or growth strategy.
Loading editor...
rust