100 Rust practice problems with solutions

Staring at Rust code feels safe. Writing it feels scary.
That’s where the real learning begins — and this post is built to take you from reading to doing with genuine confidence.

Here’s what’s waiting for you:

  • 100 Rust practice problems, from absolute basics to real-world patterns.
  • Clear, step-by-step solutions — never just “here’s the answer,” always “here’s why it works.”
  • Challenges packed with ownership, borrowing, lifetimes, enums, pattern matching, traits, and concurrency.

How it works:

  1. Read the plain-language problem.
  2. Try solving it yourself — yes, struggle a little, that’s growth.
  3. Check the solution and understand the logic deeply.
  4. Repeat until writing idiomatic Rust feels natural.

Why does practice matter so much? Rust is a language that rewards muscle memory and clear mental models. Every problem you solve makes ownership rules second nature, turns compiler messages into friendly hints, and builds the kind of skill that technical interviews and production code demand.

Whether you’re falling in love with systems programming or preparing for your next big role, these exercises will make you feel capable, creative, and ready. Pick a problem. Start today. Your “I really get Rust now!” moment is closer than you think.

Also try it: 100 C++ practice problems with solutions

1. Hello, World!

Print “Hello, World!” to the console.

rust

fn main() {
    println!("Hello, World!");
}

2. Declare Mutable and Immutable Variables

Create an immutable variable x with value 5, and a mutable variable y with value 10, then print them.

rust

fn main() {
    let x = 5;
    let mut y = 10;
    println!("x = {}, y = {}", x, y);
    y = 15;
    println!("y = {}", y);
}

3. Basic Function

Write a function add that takes two integers and returns their sum.

rust

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    println!("3 + 5 = {}", add(3, 5));
}

4. If‑else Condition

Write a function that returns "even" if a number is even, "odd" otherwise.

rust

fn even_or_odd(n: i32) -> &'static str {
    if n % 2 == 0 {
        "even"
    } else {
        "odd"
    }
}

5. Loop to Sum 1..100

Compute the sum of integers from 1 to 100 using a loop.

rust

fn main() {
    let mut sum = 0;
    let mut n = 1;
    loop {
        sum += n;
        n += 1;
        if n > 100 { break; }
    }
    println!("Sum = {}", sum);
}

6. For Loop Over Range

Print numbers from 1 to 5 using a for loop.

rust

fn main() {
    for i in 1..=5 {
        println!("{}", i);
    }
}

7. While Loop Factorial

Calculate factorial of 5 using a while loop.

rust

fn main() {
    let mut n = 5;
    let mut fact = 1;
    while n > 0 {
        fact *= n;
        n -= 1;
    }
    println!("5! = {}", fact);
}

8. String Slicing

Given a string literal, return the first word (characters until a space).

rust

fn first_word(s: &str) -> &str {
    match s.split_whitespace().next() {
        Some(word) => word,
        None => s,
    }
}
fn main() {
    println!("{}", first_word("Hello world"));
}

9. Ownership: Move Semantics

Create a String, move it to a new variable, and show that the old variable cannot be used.

rust

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;           // s1 moved
    // println!("{}", s1); // error!
    println!("{}", s2);
}

10. Borrowing with References

Write a function that takes a reference to a String and prints its length without taking ownership.

rust

fn print_length(s: &String) {
    println!("Length: {}", s.len());
}
fn main() {
    let s = String::from("hello");
    print_length(&s);
    println!("Still own: {}", s);
}

11. Mutable Reference

Write a function that pushes a character to a mutable String.

rust

fn add_exclamation(s: &mut String) {
    s.push('!');
}
fn main() {
    let mut text = String::from("Hello");
    add_exclamation(&mut text);
    println!("{}", text);
}

12. Dangling Reference (Prevented by compiler)

Comment: Rust prevents returning a reference to a local variable.

rust

// This won't compile:
// fn dangle() -> &String {
//     let s = String::from("hello");
//     &s
// }
// Instead return the String directly.
fn no_dangle() -> String {
    String::from("hello")
}

13. Struct Definition and Instantiation

Define a Rectangle struct with width and height, and create an instance.

rust

struct Rectangle {
    width: u32,
    height: u32,
}
fn main() {
    let rect = Rectangle { width: 30, height: 50 };
    println!("{}x{}", rect.width, rect.height);
}

14. Struct Method

Implement a method area for Rectangle.

rust

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
fn main() {
    let rect = Rectangle { width: 30, height: 50 };
    println!("Area = {}", rect.area());
}

15. Struct Associated Function

Add an associated function square(size) that returns a Rectangle with equal width and height.

rust

impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle { width: size, height: size }
    }
}
fn main() {
    let sq = Rectangle::square(25);
    println!("Square: {}x{}", sq.width, sq.height);
}

16. Tuple Struct

Define a Color tuple struct with r, g, b and create an instance.

rust

struct Color(u8, u8, u8);
fn main() {
    let red = Color(255, 0, 0);
    println!("Red: {}, {}, {}", red.0, red.1, red.2);
}

17. Enums: Basic

Define an enum IpAddrKind with V4 and V6 variants and create instances.

rust

enum IpAddrKind {
    V4,
    V6,
}
fn main() {
    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;
}

18. Enum with Data

Make the enum hold the actual address: V4(u8,u8,u8,u8) and V6(String).

rust

enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}
fn main() {
    let home = IpAddr::V4(127, 0, 0, 1);
    let loopback = IpAddr::V6(String::from("::1"));
}

19. Enum Method

Implement a method describe for a TrafficLight enum (Red, Yellow, Green) that returns a description.

rust

enum TrafficLight {
    Red,
    Yellow,
    Green,
}
impl TrafficLight {
    fn describe(&self) -> &str {
        match self {
            TrafficLight::Red => "Stop",
            TrafficLight::Yellow => "Caution",
            TrafficLight::Green => "Go",
        }
    }
}

20. Match with Exhaustive Arms

Write a function that takes an Option<i32> and returns the value inside, or 0 if None.

rust

fn unwrap_or_zero(opt: Option<i32>) -> i32 {
    match opt {
        Some(val) => val,
        None => 0,
    }
}

21. If-let Pattern

Use if let to print the value inside an Option only if it’s Some.

rust

fn main() {
    let config_max = Some(3u8);
    if let Some(max) = config_max {
        println!("Max = {}", max);
    }
}

22. While-let Pattern

Use while let to pop values from a vector until empty.

rust

fn main() {
    let mut stack = vec![1, 2, 3];
    while let Some(top) = stack.pop() {
        println!("{}", top);
    }
}

23. Vector Basics

Create a vector, push elements, and access by index.

rust

fn main() {
    let mut v = Vec::new();
    v.push(10);
    v.push(20);
    println!("First: {}", v[0]); // panics if oob
    println!("Get: {:?}", v.get(1)); // Some(20)
}

24. Iterate Over Vector

Use a for loop to print all elements.

rust

fn main() {
    let v = vec![1, 2, 3, 4, 5];
    for i in &v {
        println!("{}", i);
    }
}

25. Modify Vector Elements via Mutable Iteration

Double each element in a Vec<i32>.

rust

fn main() {
    let mut v = vec![1, 2, 3];
    for i in &mut v {
        *i *= 2;
    }
    println!("{:?}", v); // [2, 4, 6]
}

26. String: Creating and Concatenating

Build a String by pushing a string slice and pushing a char.

rust

fn main() {
    let mut s = String::from("Hello");
    s.push_str(" world");
    s.push('!');
    println!("{}", s);
}

27. String Format

Use format! to combine strings without moving ownership.

rust

fn main() {
    let s1 = String::from("Hello");
    let s2 = String::from("World");
    let combined = format!("{} {}", s1, s2);
    println!("{}", combined);
    println!("s1 still: {}", s1); // s1 not moved
}

28. Hash Map: Insert and Access

Create a HashMap and insert key-value pairs; then access a key.

rust

use std::collections::HashMap;
fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
    println!("{:?}", scores.get("Blue")); // Some(10)
}

29. Hash Map: Entry API

Count occurrences of words in a sentence.

rust

fn main() {
    let text = "hello world hello rust";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }
    println!("{:?}", map);
}

30. Result Type: Basic Handling

Write a function that converts a string to an integer, returning a Result.

rust

fn parse_number(s: &str) -> Result<i32, std::num::ParseIntError> {
    s.parse::<i32>()
}
fn main() {
    match parse_number("42") {
        Ok(n) => println!("Number: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

31. Unwrapping and Expect

Use unwrap and expect on a valid Option.

rust

fn main() {
    let x = Some(5);
    println!("{}", x.unwrap());
    println!("{}", x.expect("Should have value"));
}

32. Propagating Errors with ?

Write a function that reads the first line of a file and returns the length, using ? to propagate errors.

rust

use std::fs;
fn file_first_line_length(path: &str) -> Result<usize, std::io::Error> {
    let content = fs::read_to_string(path)?;
    Ok(content.lines().next().unwrap_or("").len())
}

33. Custom Error Type with Debug and Display

Create a simple custom error struct and implement traits.

rust

#[derive(Debug)]
struct MyError {
    msg: String,
}
impl std::fmt::Display for MyError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "MyError: {}", self.msg)
    }
}
impl std::error::Error for MyError {}
fn main() {
    let err = MyError { msg: String::from("something wrong") };
    println!("{}", err);
}

34. Generic Function: Largest

Write a generic function largest<T: PartialOrd + Clone> that returns the largest element from a slice.

rust

fn largest<T: PartialOrd + Clone>(list: &[T]) -> T {
    let mut largest = list[0].clone();
    for item in list.iter() {
        if item > &largest {
            largest = item.clone();
        }
    }
    largest
}
fn main() {
    let numbers = vec![3, 5, 2, 8, 1];
    println!("Largest: {}", largest(&numbers));
}

35. Generic Struct

Define a Point struct with two fields of generic type T.

rust

struct Point<T> {
    x: T,
    y: T,
}
fn main() {
    let integer_point = Point { x: 5, y: 10 };
    let float_point = Point { x: 1.0, y: 4.0 };
}

36. Method with Generic Type and Constraints

Implement a method x on Point<T> that returns a reference to x.

rust

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

37. Traits: Define and Implement

Define a trait Summary with a method summarize, and implement it for NewsArticle.

rust

trait Summary {
    fn summarize(&self) -> String;
}
struct NewsArticle {
    headline: String,
    author: String,
}
impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{} by {}", self.headline, self.author)
    }
}

38. Trait Bound Function

Write a function that takes any type implementing Summary and prints it.

rust

fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}

39. Derivable Traits

Use #[derive(Debug, Clone, PartialEq)] on a struct.

rust

#[derive(Debug, Clone, PartialEq)]
struct User {
    name: String,
    age: u8,
}
fn main() {
    let u1 = User { name: String::from("Alice"), age: 30 };
    let u2 = u1.clone();
    println!("{:?}", u2);
    assert_eq!(u1, u2);
}

40. Lifetimes in Functions

Write a function longest that returns the longer of two string slices, using explicit lifetime annotation.

rust

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}
fn main() {
    let s1 = "hello";
    let s2 = "world!";
    println!("Longer: {}", longest(s1, s2));
}

41. Iterator: Map and Collect

Take a vector, apply map to double each element, and collect into a new vector.

rust

fn main() {
    let v = vec![1, 2, 3, 4, 5];
    let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
    println!("{:?}", doubled);
}

42. Filtering

From a vector of integers, filter out the even numbers.

rust

fn main() {
    let nums = vec![1, 2, 3, 4, 5, 6];
    let odds: Vec<_> = nums.into_iter().filter(|x| x % 2 != 0).collect();
    println!("{:?}", odds);
}

43. Fold (Reduce)

Sum all elements using fold.

rust

fn main() {
    let numbers = [1, 2, 3, 4, 5];
    let sum = numbers.iter().fold(0, |acc, x| acc + x);
    println!("Sum = {}", sum);
}

44. Any and All

Check if all numbers are positive and if any is even.

rust

fn main() {
    let v = vec![2, 4, 6];
    let all_positive = v.iter().all(|&x| x > 0);
    let any_even = v.iter().any(|&x| x % 2 == 0);
    println!("All positive: {}, Any even: {}", all_positive, any_even);
}

45. Enumerate

Iterate with index using enumerate.

rust

fn main() {
    let names = vec!["Alice", "Bob", "Carol"];
    for (i, name) in names.iter().enumerate() {
        println!("{}. {}", i + 1, name);
    }
}

46. Chaining Iterator Methods

Take a vector of words, filter those with length > 3, convert to uppercase, collect.

rust

fn main() {
    let words = vec!["hi", "hello", "rust", "ok"];
    let result: Vec<_> = words.into_iter()
        .filter(|w| w.len() > 3)
        .map(|w| w.to_uppercase())
        .collect();
    println!("{:?}", result);
}

47. Closures: Capture Environment

Create a closure that captures a variable and increments it.

rust

fn main() {
    let mut count = 0;
    let mut inc = || {
        count += 1;
        count
    };
    println!("{}", inc()); // 1
    println!("{}", inc()); // 2
}

Also try it: 100 MongoDB practice problems with solutions

48. Closure as Argument to Custom Function

Write a function apply that takes a closure and a value, and returns the closure applied to the value.

rust

fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
    f(x)
}
fn main() {
    let square = |n| n * n;
    println!("{}", apply(square, 5));
}

49. Threads: Spawn a Basic Thread

Spawn a new thread that prints a message and then join it.

rust

use std::thread;
fn main() {
    let handle = thread::spawn(|| {
        println!("Hello from thread");
    });
    handle.join().unwrap();
}

50. Share Data with Arc and Mutex

Count from 1 to 10 using multiple threads, sharing a counter safely.

rust

use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        }));
    }
    for handle in handles {
        handle.join().unwrap();
    }
    println!("Result: {}", *counter.lock().unwrap());
}

51. Channels: Sending a Message

Create a channel, send a string from one thread, and receive in main.

rust

use std::sync::mpsc;
use std::thread;
fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        tx.send(String::from("hello")).unwrap();
    });
    println!("Received: {}", rx.recv().unwrap());
}

52. Multiple Messages and Iteration

Send multiple numbers and iterate the receiver.

rust

fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        for i in 1..=5 {
            tx.send(i).unwrap();
        }
    });
    for received in rx {
        println!("Got: {}", received);
    }
}

53. Smart Pointer: Box

Use Box to store a recursive data type: a cons list.

rust

enum List {
    Cons(i32, Box<List>),
    Nil,
}
use List::{Cons, Nil};
fn main() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}

54. Smart Pointer: Deref and Drop

Implement Deref for a custom smart pointer MyBox and observe Drop.

rust

struct MyBox<T>(T);
impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> { MyBox(x) }
}
impl<T> std::ops::Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &T { &self.0 }
}
impl<T> Drop for MyBox<T> {
    fn drop(&mut self) {
        println!("Dropping MyBox");
    }
}
fn main() {
    let x = MyBox::new(5);
    println!("{}", *x); // deref
}

55. Reference Counting Rc

Share a resource like String between multiple owners using Rc.

rust

use std::rc::Rc;
fn main() {
    let value = Rc::new(String::from("shared"));
    let a = Rc::clone(&value);
    let b = Rc::clone(&value);
    println!("Count: {}", Rc::strong_count(&value)); // 3
}

56. RefCell for Interior Mutability

Mutate data through an immutable reference.

rust

use std::cell::RefCell;
fn main() {
    let x = RefCell::new(5);
    let y = &x;
    *y.borrow_mut() = 10;
    println!("{}", x.borrow());
}

57. Combine Rc<RefCell<T>> for Mutable Shared State

rust

use std::rc::Rc;
use std::cell::RefCell;
fn main() {
    let data = Rc::new(RefCell::new(0));
    let data1 = Rc::clone(&data);
    let data2 = Rc::clone(&data);
    *data1.borrow_mut() += 1;
    *data2.borrow_mut() += 2;
    println!("{}", data.borrow()); // 3
}

58. File Reading (with error handling)

Read a file to string and handle potential error.

rust

use std::fs;
fn main() -> Result<(), std::io::Error> {
    let content = fs::read_to_string("input.txt")?;
    println!("{}", content);
    Ok(())
}

59. Write to File

Write a string to a new file.

rust

use std::fs;
fn main() -> Result<(), std::io::Error> {
    fs::write("output.txt", "Hello, Rust!")?;
    Ok(())
}

60. Environment Variables

Read an environment variable HOME and print it.

rust

use std::env;
fn main() {
    match env::var("HOME") {
        Ok(path) => println!("Home: {}", path),
        Err(e) => println!("Error: {}", e),
    }
}

61. Command-Line Arguments

Print all command-line arguments.

rust

use std::env;
fn main() {
    let args: Vec<String> = env::args().collect();
    println!("{:?}", args);
}

62. Parse Integer from CLI Argument

Read first argument, parse to i32, and print double.

rust

use std::env;
fn main() {
    if let Some(arg) = env::args().nth(1) {
        match arg.parse::<i32>() {
            Ok(n) => println!("Double: {}", n * 2),
            Err(_) => println!("Not a number"),
        }
    } else {
        println!("No argument");
    }
}

63. Recursion: Factorial

Compute factorial using recursion.

rust

fn factorial(n: u64) -> u64 {
    match n {
        0 => 1,
        _ => n * factorial(n - 1),
    }
}
fn main() {
    println!("5! = {}", factorial(5));
}

64. Recursion: Fibonacci

Return the nth Fibonacci number (recursive, inefficient but simple).

rust

fn fibonacci(n: u32) -> u64 {
    if n <= 1 { n as u64 }
    else { fibonacci(n - 1) + fibonacci(n - 2) }
}
fn main() {
    println!("fib(10) = {}", fibonacci(10));
}

65. Fibonacci with Memoization (HashMap)

Implement Fibonacci using a cache to avoid recomputation.

rust

use std::collections::HashMap;
fn fib_memo(n: u32, cache: &mut HashMap<u32, u64>) -> u64 {
    if let Some(&val) = cache.get(&n) { return val; }
    let result = match n {
        0 => 0,
        1 => 1,
        _ => fib_memo(n - 1, cache) + fib_memo(n - 2, cache),
    };
    cache.insert(n, result);
    result
}
fn main() {
    let mut cache = HashMap::new();
    println!("fib(30) = {}", fib_memo(30, &mut cache));
}

66. Bubble Sort

Implement bubble sort for a mutable slice.

rust

fn bubble_sort<T: PartialOrd>(arr: &mut [T]) {
    let len = arr.len();
    for i in 0..len {
        for j in 0..len - i - 1 {
            if arr[j] > arr[j + 1] {
                arr.swap(j, j + 1);
            }
        }
    }
}
fn main() {
    let mut v = [3, 1, 4, 1, 5, 9, 2, 6];
    bubble_sort(&mut v);
    println!("{:?}", v);
}

67. Selection Sort

rust

fn selection_sort<T: PartialOrd>(arr: &mut [T]) {
    let len = arr.len();
    for i in 0..len {
        let mut min_idx = i;
        for j in i + 1..len {
            if arr[j] < arr[min_idx] { min_idx = j; }
        }
        if min_idx != i { arr.swap(i, min_idx); }
    }
}

68. Binary Search (Recursive)

rust

fn binary_search<T: Ord>(arr: &[T], target: &T) -> Option<usize> {
    if arr.is_empty() { return None; }
    let mid = arr.len() / 2;
    if &arr[mid] == target { Some(mid) }
    else if target < &arr[mid] { binary_search(&arr[..mid], target) }
    else { binary_search(&arr[mid+1..], target).map(|idx| mid + 1 + idx) }
}
fn main() {
    let v = [1, 3, 5, 7, 9];
    println!("{:?}", binary_search(&v, &5));
}

69. Check Palindrome (String)

Case-insensitive, ignore non-alphanumeric.

rust

fn is_palindrome(s: &str) -> bool {
    let cleaned: String = s.chars().filter(|c| c.is_alphanumeric()).collect();
    cleaned.to_lowercase() == cleaned.chars().rev().collect::<String>().to_lowercase()
}
fn main() {
    println!("{}", is_palindrome("A man, a plan, a canal: Panama"));
}

70. Reverse String

rust

fn reverse_string(s: &str) -> String {
    s.chars().rev().collect()
}

71. Count Character Occurrences

Count occurrences of each character in a string using a HashMap.

rust

fn char_counts(s: &str) -> HashMap<char, u32> {
    let mut map = HashMap::new();
    for ch in s.chars() {
        *map.entry(ch).or_insert(0) += 1;
    }
    map
}

72. Find Most Frequent Element in a Vector

rust

fn most_frequent(v: &[i32]) -> Option<i32> {
    let mut freq = HashMap::new();
    for &val in v {
        *freq.entry(val).or_insert(0) += 1;
    }
    freq.into_iter().max_by_key(|&(_, count)| count).map(|(val, _)| val)
}

73. Remove Duplicates from a Vector

Preserving order using a set.

rust

fn remove_duplicates<T: Eq + Hash + Clone>(v: &[T]) -> Vec<T> {
    let mut seen = std::collections::HashSet::new();
    let mut res = Vec::new();
    for item in v {
        if seen.insert(item.clone()) {
            res.push(item.clone());
        }
    }
    res
}

74. Merge Two Sorted Vectors

rust

fn merge_sorted(a: &[i32], b: &[i32]) -> Vec<i32> {
    let mut res = Vec::with_capacity(a.len() + b.len());
    let (mut i, mut j) = (0, 0);
    while i < a.len() && j < b.len() {
        if a[i] <= b[j] { res.push(a[i]); i += 1; }
        else { res.push(b[j]); j += 1; }
    }
    res.extend_from_slice(&a[i..]);
    res.extend_from_slice(&b[j..]);
    res
}

75. Generate Prime Numbers up to N (Sieve of Eratosthenes)

rust

fn primes_up_to(n: usize) -> Vec<usize> {
    if n < 2 { return vec![]; }
    let mut is_prime = vec![true; n + 1];
    is_prime[0] = false;
    is_prime[1] = false;
    for i in 2..=(n as f64).sqrt() as usize {
        if is_prime[i] {
            for j in (i * i..=n).step_by(i) {
                is_prime[j] = false;
            }
        }
    }
    is_prime.iter().enumerate().filter(|(_, &p)| p).map(|(i, _)| i).collect()
}

76. Check if a Number is Prime

rust

fn is_prime(n: u64) -> bool {
    if n < 2 { return false; }
    for i in 2..=(n as f64).sqrt() as u64 {
        if n % i == 0 { return false; }
    }
    true
}

77. GCD (Euclidean Algorithm)

rust

fn gcd(a: u64, b: u64) -> u64 {
    if b == 0 { a } else { gcd(b, a % b) }
}

78. LCM

rust

fn lcm(a: u64, b: u64) -> u64 {
    a * b / gcd(a, b)
}

79. Convert String to Number with Error Handling

Parse and handle error gracefully using match.

rust

fn parse_i32(s: &str) -> i32 {
    s.parse().unwrap_or(0)
}

80. Read CSV Line by Line (Simplified)

Read lines from a hardcoded string and print values.

rust

fn main() {
    let data = "name,age\nAlice,30\nBob,25";
    for line in data.lines() {
        let fields: Vec<&str> = line.split(',').collect();
        println!("{:?}", fields);
    }
}

81. Simple Unit Test

Write a test for the add function.

rust

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
    }
}

82. Implement a Counter Struct (Iterator)

Create a struct Counter that counts from start to end and implement Iterator.

rust

struct Counter {
    current: i32,
    end: i32,
}
impl Counter {
    fn new(start: i32, end: i32) -> Counter { Counter { current: start, end } }
}
impl Iterator for Counter {
    type Item = i32;
    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.end {
            let val = self.current;
            self.current += 1;
            Some(val)
        } else {
            None
        }
    }
}
fn main() {
    let c = Counter::new(1, 5);
    for i in c { println!("{}", i); }
}

83. Implementing Default Trait

rust

#[derive(Default)]
struct Config {
    timeout: u32,
    retries: u32,
}
fn main() {
    let config = Config { timeout: 30, ..Default::default() };
    println!("{}, {}", config.timeout, config.retries);
}

Also try it: 100 Azure practice problems with solutions

84. Implementing From Trait for Type Conversion

Convert a Person into a String.

rust

struct Person { name: String, age: u8 }
impl From<Person> for String {
    fn from(p: Person) -> String {
        format!("{} ({})", p.name, p.age)
    }
}
fn main() {
    let p = Person { name: "Alice".into(), age: 30 };
    let s: String = p.into();
    println!("{}", s);
}

85. ToString and Display

rust

use std::fmt;
impl fmt::Display for Person {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} is {} years old", self.name, self.age)
    }
}

86. Implement a Simple Stack Using Vec

rust

struct Stack<T> {
    items: Vec<T>,
}
impl<T> Stack<T> {
    fn new() -> Self { Stack { items: vec![] } }
    fn push(&mut self, item: T) { self.items.push(item); }
    fn pop(&mut self) -> Option<T> { self.items.pop() }
    fn peek(&self) -> Option<&T> { self.items.last() }
}

87. Implement a Simple Queue Using VecDeque

rust

use std::collections::VecDeque;
struct Queue<T> { data: VecDeque<T> }
impl<T> Queue<T> {
    fn new() -> Self { Queue { data: VecDeque::new() } }
    fn enqueue(&mut self, item: T) { self.data.push_back(item); }
    fn dequeue(&mut self) -> Option<T> { self.data.pop_front() }
    fn len(&self) -> usize { self.data.len() }
}

88. Split a String into Words and Count Unique

rust

fn unique_words(text: &str) -> usize {
    let set: std::collections::HashSet<_> = text.split_whitespace().collect();
    set.len()
}

89. FizzBuzz (1 to 100)

rust

fn main() {
    for i in 1..=100 {
        if i % 15 == 0 { println!("FizzBuzz"); }
        else if i % 3 == 0 { println!("Fizz"); }
        else if i % 5 == 0 { println!("Buzz"); }
        else { println!("{}", i); }
    }
}

90. Sum of Digits

rust

fn sum_of_digits(mut n: u32) -> u32 {
    let mut sum = 0;
    while n > 0 { sum += n % 10; n /= 10; }
    sum
}

91. Factorial Using fold (1..=n)

rust

fn factorial_fold(n: u32) -> u32 {
    (1..=n).fold(1, |acc, x| acc * x)
}

92. Find Duplicate Elements in a Vector

rust

fn find_duplicates<T: Eq + Hash + Clone>(v: &[T]) -> Vec<T> {
    let mut seen = HashSet::new();
    let mut duplicates = Vec::new();
    for item in v {
        if !seen.insert(item.clone()) {
            duplicates.push(item.clone());
        }
    }
    duplicates
}

93. Rotate a Vector Right by K

rust

fn rotate_right(v: &[i32], k: usize) -> Vec<i32> {
    let len = v.len();
    if len == 0 { return v.to_vec(); }
    let k = k % len;
    [&v[len - k..], &v[..len - k]].concat()
}

94. Transpose a 2D Matrix (Square)

rust

fn transpose(matrix: &Vec<Vec<i32>>) -> Vec<Vec<i32>> {
    let n = matrix.len();
    let mut result = vec![vec![0; n]; n];
    for i in 0..n {
        for j in 0..n {
            result[j][i] = matrix[i][j];
        }
    }
    result
}

95. Check if a String Contains All Unique Characters

rust

fn all_unique(s: &str) -> bool {
    let mut seen = HashSet::new();
    for ch in s.chars() {
        if !seen.insert(ch) { return false; }
    }
    true
}

96. CamelCase to snake_case Conversion

rust

fn camel_to_snake(s: &str) -> String {
    let mut out = String::new();
    for (i, ch) in s.chars().enumerate() {
        if ch.is_uppercase() {
            if i != 0 { out.push('_'); }
            out.push(ch.to_ascii_lowercase());
        } else {
            out.push(ch);
        }
    }
    out
}

97. Generate Random Number Between 1 and 10

rust

use rand::Rng;
fn main() {
    let num = rand::thread_rng().gen_range(1..=10);
    println!("{}", num);
}

98. Time a Function Execution

Measure elapsed time for a function call.

rust

use std::time::Instant;
fn main() {
    let start = Instant::now();
    // some computation
    let duration = start.elapsed();
    println!("Time: {:?}", duration);
}

99. Simple Configuration Struct with Builder Pattern

rust

#[derive(Debug, Default)]
struct ConfigBuilder {
    timeout: Option<u32>,
    retries: Option<u32>,
}
impl ConfigBuilder {
    fn timeout(mut self, val: u32) -> Self { self.timeout = Some(val); self }
    fn retries(mut self, val: u32) -> Self { self.retries = Some(val); self }
    fn build(self) -> Config2 {
        Config2 {
            timeout: self.timeout.unwrap_or(30),
            retries: self.retries.unwrap_or(3),
        }
    }
}
struct Config2 { timeout: u32, retries: u32 }
fn main() {
    let config = ConfigBuilder::default().timeout(60).build();
    println!("{:?}", (config.timeout, config.retries));
}

100. Simple HTTP GET Request (using reqwest blocking)

Fetch the content of a URL and print the length.

rust

// Cargo.toml: reqwest = { version = "0.11", features = ["blocking"] }
use reqwest;
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let body = reqwest::blocking::get("https://www.rust-lang.org")?.text()?;
    println!("Length: {}", body.len());
    Ok(())
}

100 Dart practice problems with solutions

Conclusion: Forged Stronger with Rust

Completing these 100 Rust practice problems with solutions is not just about writing code—it’s about building patience, discipline, and confidence. Rust is known for challenging developers, and every problem you solved proves that you didn’t give up when things got tough.

There were moments when errors felt confusing and solutions seemed far away, but each struggle taught you something valuable. Every fix, every success, and every lesson learned made you stronger as a programmer.

Remember, mastering Rust is like forging steel—it takes time, pressure, and persistence. Keep going, trust your progress, and never doubt your ability to grow. This is not the end of your Rust journey—it’s the moment where your real confidence begins.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top