aayush@ate_
cd ../notes
languages

Rust

obsidian source → .md

download

https://toml.io/en/ for rust implementation https://doc.rust-lang.org/book/title-page.html rust tutorial https://cheats.rs

(media not in this export — contact me for the full note)

Rust

Hello World:

// hello_world.rs
fn main() {
    println!("Hello, World!"); // println! is a macro
}

If-Else Question Program:

// if_else_example.rs
use std::io; // Required for input/output operations

fn main() {
    println!("Enter an integer:");

    let mut input = String::new(); // Create a mutable string to store input

    // Read a line from stdin
    io::stdin().read_line(&mut input)
        .expect("Failed to read line"); // Handle potential error

    // Trim whitespace and parse the string to an integer
    let number: i32 = match input.trim().parse() {
        Ok(num) => num, // Successfully parsed
        Err(_) => { // Failed to parse
            println!("Invalid input. Please enter an integer.");
            return; // Exit the program
        }
    };

    // If-else if-else statement (no parentheses around conditions in Rust)
    if number > 0 {
        println!("The number {} is positive.", number);
    } else if number == 0 {
        println!("The number {} is zero.", number);
    } else {
        println!("The number {} is negative.", number);
    }
}

How to run Rust:
Save the code as a .rs file. You need Rust installed (via rustup).

  1. Compile: rustc hello_world.rs

  2. Run: ./hello_world

    For the if-else example:

  3. Compile: rustc if_else_example.rs

  4. Run: ./if_else_example

Rust Implementations

Place the following snippets in a Rust file (for example, main.rs) and run with cargo run or rustc main.rs && ./main.

Tip: For clarity, each example is separated by a comment header.


→ Vec<u64> specifies the return type of the Rust function.

Return Type Meaning

In Rust function signatures, the arrow separates parameters from the return type. Here, Vec<u64> means the function returns ownership of a growable vector containing unsigned 64-bit integers (u64).

Vec Details

  • Vec<T> is Rust’s standard contiguous, dynamically-sized array that can grow or shrink at runtime.
  • u64 is a primitive unsigned 64-bit integer (0 to 18,446,744,073,709,551,615), ideal for Fibonacci numbers up to large indices before overflow.


Number Logic Programs in Rust

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

fn demo_prime() {
    let num = 29;
    println!("{} is prime? {}", num, is_prime(num));
    // Expected Output: "29 is prime? true"
}
  1. Fibonacci Series
fn fibonacci(n: usize) -> Vec<u64> {
    let mut series = Vec::with_capacity(n);
    let (mut a, mut b) = (0, 1);
    for _ in 0..n {
        series.push(a);
        let temp = a + b;
        a = b;
        b = temp;
    }
    series
}

fn demo_fibonacci() {
    println!("Fibonacci series: {:?}", fibonacci(10));
    // Expected Output: "Fibonacci series: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]"
}
  1. Factorial
fn factorial(n: u64) -> u64 {
    if n == 0 { 1 } else { n * factorial(n - 1) }
}

fn demo_factorial() {
    let num = 5;
    println!("Factorial of {}: {}", num, factorial(num));
    // Expected Output: "Factorial of 5: 120"
}
  1. Armstrong Number
fn is_armstrong(num: u32) -> bool {
    let digits: Vec<u32> = num
        .to_string()
        .chars()
        .filter_map(|c| c.to_digit(10))
        .collect();
    let power = digits.len() as u32;
    let sum: u32 = digits.iter().map(|&d| d.pow(power)).sum();
    sum == num
}

fn demo_armstrong() {
    let num = 153;
    println!("{} is Armstrong? {}", num, is_armstrong(num));
    // Expected Output: "153 is Armstrong? true"
}
  1. Palindrome Number
fn is_palindrome(num: i32) -> bool {
    let s = num.to_string();
    s == s.chars().rev().collect::<String>()
}

fn demo_palindrome() {
    let num = 121;
    println!("{} is palindrome? {}", num, is_palindrome(num));
    // Expected Output: "121 is palindrome? true"
}
  1. GCD and LCM
fn gcd(a: i32, b: i32) -> i32 {
    if b == 0 { a } else { gcd(b, a % b) }
}

fn lcm(a: i32, b: i32) -> i32 {
    (a * b).abs() / gcd(a, b)
}

fn demo_gcd_lcm() {
    println!("GCD of 54 and 24: {}", gcd(54, 24)); // Expected: 6
    println!("LCM of 12 and 18: {}", lcm(12, 18)); // Expected: 36
}
  1. Reverse a Number & Sum of Digits
fn reverse_number(num: i32) -> i32 {
    num.to_string()
       .chars()
       .rev()
       .collect::<String>()
       .parse::<i32>()
       .unwrap_or(0)
}

fn sum_of_digits(num: i32) -> i32 {
    num.to_string()
       .chars()
       .filter_map(|c| c.to_digit(10))
       .map(|d| d as i32)
       .sum()
}

fn demo_reverse_and_sum() {
    let num = 12345;
    println!("Reverse of {}: {}", num, reverse_number(num)); // Expected: 54321
    println!("Sum of digits of {}: {}", 1234, sum_of_digits(1234)); // Expected: 10
}

Array Programs in Rust

  1. Linear Search
fn linear_search(arr: &[i32], target: i32) -> Option<usize> {
    arr.iter().position(|&x| x == target)
}

fn demo_linear_search() {
    let arr = [10, 20, 30, 40, 50];
    let target = 30;
    println!("Position of {}: {:?}", target, linear_search(&arr, target));
    // Expected Output: "Position of 30: Some(2)"
}
  1. Binary Search
fn binary_search(arr: &[i32], target: i32) -> Option<usize> {
    let (mut low, mut high) = (0, arr.len() as i32 - 1);
    while low <= high {
        let mid = (low + high) / 2;
        if arr[mid as usize] == target {
            return Some(mid as usize);
        } else if arr[mid as usize] < target {
            low = mid + 1;
        } else {
            high = mid - 1;
        }
    }
    None
}

fn demo_binary_search() {
    let arr = [10, 20, 30, 40, 50];
    let target = 40;
    println!("Position of {}: {:?}", target, binary_search(&arr, target));
    // Expected Output: "Position of 40: Some(3)"
}
  1. Bubble Sort
fn bubble_sort(arr: &mut [i32]) {
    let n = arr.len();
    for i in 0..n {
        for j in 0..(n - i - 1) {
            if arr[j] > arr[j + 1] {
                arr.swap(j, j + 1);
            }
        }
    }
}

fn demo_bubble_sort() {
    let mut arr = [64, 34, 25, 12, 22, 11, 90];
    bubble_sort(&mut arr);
    println!("Sorted array: {:?}", arr);
    // Expected Output: "Sorted array: [11, 12, 22, 25, 34, 64, 90]"
}
  1. Selection Sort
fn selection_sort(arr: &mut [i32]) {
    let n = arr.len();
    for i in 0..n {
        let mut min_idx = i;
        for j in (i + 1)..n {
            if arr[j] < arr[min_idx] {
                min_idx = j;
            }
        }
        arr.swap(i, min_idx);
    }
}

fn demo_selection_sort() {
    let mut arr = [64, 25, 12, 22, 11];
    selection_sort(&mut arr);
    println!("Selection sorted: {:?}", arr);
    // Expected Output: "Selection sorted: [11, 12, 22, 25, 64]"
}
  1. Insertion Sort
fn insertion_sort(arr: &mut [i32]) {
    let n = arr.len();
    for i in 1..n {
        let key = arr[i];
        let mut j = i;
        while j > 0 && arr[j - 1] > key {
            arr[j] = arr[j - 1];
            j -= 1;
        }
        arr[j] = key;
    }
}

fn demo_insertion_sort() {
    let mut arr = [12, 11, 13, 5, 6];
    insertion_sort(&mut arr);
    println!("Insertion sorted: {:?}", arr);
    // Expected Output: "Insertion sorted: [5, 6, 11, 12, 13]"
}
  1. Second Largest Element
fn second_largest(arr: &[i32]) -> Option<i32> {
    if arr.len() < 2 { return None; }
    let mut first = i32::MIN;
    let mut second = i32::MIN;
    for &num in arr {
        if num > first {
            second = first;
            first = num;
        } else if num > second && num != first {
            second = num;
        }
    }
    if second == i32::MIN { None } else { Some(second) }
}

fn demo_second_largest() {
    let arr = [12, 35, 1, 10, 34, 1];
    println!("Second largest: {:?}", second_largest(&arr));
    // Expected Output: "Second largest: Some(34)"
}
  1. Array Rotation
fn rotate_array(arr: &[i32], k: usize) -> Vec<i32> {
    let len = arr.len();
    let k = k % len;
    [&arr[k..], &arr[..k]].concat()
}

fn demo_array_rotation() {
    let arr = [1, 2, 3, 4, 5, 6, 7];
    println!("Rotated array: {:?}", rotate_array(&arr, 3));
    // Expected Output: "Rotated array: [4, 5, 6, 7, 1, 2, 3]"
}
  1. Remove Duplicates
use std::collections::LinkedHashSet;

fn remove_duplicates(arr: &[i32]) -> Vec<i32> {
    let mut set = LinkedHashSet::new();
    for &num in arr {
        set.insert(num);
    }
    set.into_iter().collect()
}

fn demo_remove_duplicates() {
    let arr = [1, 2, 2, 3, 4, 4, 5];
    println!("Without duplicates: {:?}", remove_duplicates(&arr));
    // Expected Output: "Without duplicates: [1, 2, 3, 4, 5]"
}
  1. Merge Two Arrays
fn merge_arrays(arr1: &[i32], arr2: &[i32]) -> Vec<i32> {
    let mut merged = [arr1, arr2].concat();
    merged.sort();
    merged
}

fn demo_merge_arrays() {
    let arr1 = [1, 3, 5, 7];
    let arr2 = [2, 4, 6, 8];
    println!("Merged array: {:?}", merge_arrays(&arr1, &arr2));
    // Expected Output: "Merged array: [1, 2, 3, 4, 5, 6, 7, 8]"
}
  1. Matrix Addition & Multiplication
fn matrix_addition(a: &Vec<Vec<i32>>, b: &Vec<Vec<i32>>) -> Vec<Vec<i32>> {
    a.iter().zip(b.iter())
     .map(|(row_a, row_b)| row_a.iter().zip(row_b.iter()).map(|(x, y)| x + y).collect())
     .collect()
}

fn matrix_multiplication(a: &Vec<Vec<i32>>, b: &Vec<Vec<i32>>) -> Vec<Vec<i32>> {
    let m = a.len();
    let n = b[0].len();
    let mut result = vec![vec![0; n]; m];
    for i in 0..m {
        for j in 0..n {
            for k in 0..b.len() {
                result[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    result
}

fn demo_matrices() {
    let a = vec![vec![1, 2], vec![3, 4]];
    let b = vec![vec![5, 6], vec![7, 8]];
    println!("Matrix addition: {:?}", matrix_addition(&a, &b));
    // Expected Output: "Matrix addition: [[6, 8], [10, 12]]"
    let c = vec![vec![2, 0], vec![1, 2]];
    println!("Matrix multiplication: {:?}", matrix_multiplication(&a, &c));
    // Expected Output: "Matrix multiplication: [[4, 4], [10, 8]]"
}
  1. Transpose Matrix
fn transpose(matrix: &Vec<Vec<i32>>) -> Vec<Vec<i32>> {
    let rows = matrix.len();
    let cols = matrix[0].len();
    let mut transposed = vec![vec![0; rows]; cols];
    for i in 0..rows {
        for j in 0..cols {
            transposed[j][i] = matrix[i][j];
        }
    }
    transposed
}

fn demo_transpose() {
    let matrix = vec![vec![1, 2, 3], vec![4, 5, 6]];
    println!("Transpose: {:?}", transpose(&matrix));
    // Expected Output: "Transpose: [[1, 4], [2, 5], [3, 6]]"
}
  1. Frequency of Elements
use std::collections::HashMap;

fn frequency_count(arr: &[i32]) -> HashMap<i32, i32> {
    let mut freq = HashMap::new();
    for &num in arr {
        *freq.entry(num).or_insert(0) += 1;
    }
    freq
}

fn demo_frequency() {
    let arr = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
    println!("Frequency: {:?}", frequency_count(&arr));
    // Expected Output (order may vary): "Frequency: {1: 1, 2: 2, 3: 3, 4: 4}"
}

arr: &i32 and related syntax define precise type annotations for safe, borrowed access to array data in Rust functions.

Parameter Syntax Breakdown

  • arr is the parameter name.
  • : separates name from type (required for all parameters).
  • & denotes a borrow/reference — non-owning pointer to data elsewhere.
  • i32 is a slice type: unsized view over contiguous i32 (32-bit signed integer) elements.
  • Combined &i32 = borrowed slice: runtime-length, read-only array reference (zero-cost abstraction).

Return Type Syntax

  • -> mandates explicit return type (unlike implicit () unit).
  • HashMap<K, V> is generic: angle brackets < > specify type parameters.
  • i32, i32 = key-value types (both 32-bit signed ints for number → frequency mapping).

Loop Pattern Syntax

  • for ... in ITERABLE iterates owned values.
  • &num = ref pattern: & destructures borrowed &i32 into owned i32 copy (via Copy trait).
  • num becomes i32 variable per iteration (no further borrow).

  1. Find Missing Number
fn find_missing_number(arr: &[i32], n: i32) -> i32 {
    let total_sum = n * (n + 1) / 2;
    let arr_sum: i32 = arr.iter().sum();
    total_sum - arr_sum
}

fn demo_missing_number() {
    let arr = [1, 2, 4, 5, 6]; // Missing 3 in 1..6
    println!("Missing number: {}", find_missing_number(&arr, 6));
    // Expected Output: "Missing number: 3"
}

Advanced Array Programs in Rust

  1. Two Sum Problem
use std::collections::HashMap;

fn two_sum(arr: &[i32], target: i32) -> Option<(usize, usize)> {
    let mut seen = HashMap::new();
    for (i, &num) in arr.iter().enumerate() {
        if let Some(&j) = seen.get(&(target - num)) {
            return Some((j, i));
        }
        seen.insert(num, i);
    }
    None
}

fn demo_two_sum() {
    let arr = [2, 7, 11, 15];
    println!("Two sum indices: {:?}", two_sum(&arr, 9));
    // Expected Output: "Two sum indices: Some((0, 1))"
}
  1. Maximum Subarray Sum (Kadane's Algorithm)
fn max_subarray_sum(arr: &[i32]) -> i32 {
    let mut max_sum = arr[0];
    let mut current_sum = arr[0];
    for &num in &arr[1..] {
        current_sum = current_sum.max(num + current_sum);
        max_sum = max_sum.max(current_sum);
    }
    max_sum
}

fn demo_max_subarray() {
    let arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4];
    println!("Maximum subarray sum: {}", max_subarray_sum(&arr));
    // Expected Output: "Maximum subarray sum: 6"
}
  1. Move Zeros to End
fn move_zeros(arr: &mut [i32]) {
    let mut non_zero_idx = 0;
    for i in 0..arr.len() {
        if arr[i] != 0 {
            arr.swap(i, non_zero_idx);
            non_zero_idx += 1;
        }
    }
}

fn demo_move_zeros() {
    let mut arr = [0, 1, 0, 3, 12];
    move_zeros(&mut arr);
    println!("After moving zeros: {:?}", arr);
    // Expected Output: "After moving zeros: [1, 3, 12, 0, 0]"
}
  1. Find All Duplicates
fn find_all_duplicates(arr: &[i32]) -> Vec<i32> {
    let mut seen = std::collections::HashSet::new();
    let mut duplicates = Vec::new();
    for &num in arr {
        if !seen.insert(num) {
            duplicates.push(num);
        }
    }
    duplicates
}

fn demo_find_duplicates() {
    let arr = [4, 3, 2, 7, 8, 2, 3, 1];
    println!("All duplicates: {:?}", find_all_duplicates(&arr));
    // Expected Output: "All duplicates: [2, 3]" (order may vary)
}
  1. Array Intersection
fn array_intersection(arr1: &[i32], arr2: &[i32]) -> Vec<i32> {
    let set1: std::collections::HashSet<_> = arr1.iter().cloned().collect();
    arr2.iter().filter(|&&x| set1.contains(&x)).cloned().collect()
}

fn demo_intersection() {
    let arr1 = [1, 2, 2, 1];
    let arr2 = [2, 2];
    println!("Intersection: {:?}", array_intersection(&arr1, &arr2));
    // Expected Output: "Intersection: [2]"
}