Techn0tz

Empowering self-learners through clean, beginner-friendly tutorials on Git, Jekyll, and more.

Feedback Form
Previous: Level 2 Rust GUI - Enhance Teacher Assistant App with Attendance, Grades, and Reports | Up: Home

📄 Introduction

Ever wondered how the same simple program can look completely different depending on the language you use?

Before jumping into Level 3 of the Teacher Assistant app, let’s take a quick Rust refresher. By comparing Rust with other popular languages on simple programs — a relaxed way to brush up the basics

Simple programs might seem ‘too basic’ at first glance — but understanding the core logic behind them lays a strong foundation in any language. Each language has its own flavor — Python can print ‘Hello World!’ in one line, while Rust requiers a few extra steps.

That’s the fun part — we’re not chasing complex algorithms. Instead, we’ll explore 5 simple programs in Rust, C, C++, Java, and Python, so you can:

  • 👀 Spot syntax differences instantly
  • 🦀 Discover what Rust does differently (ownership, safety, strictness)
  • 💡 Pick up insights that apply even to bigger projects

By the end, you’ll see that a “basic” program is never really basic — it’s a window into how each language thinks.

Even if you’ve seen these programs before, this post gives you a side-by-side view across multiple languages, with a special focus on what Rust does differently

Ready to compare, contrast, and maybe even be surprised? Let’s start with a simple ‘swapping two numbers’ and see how each language handles it 🚀


🔃 Swapping Two Numbers

Imagine two students exchanging their seats in class — that’s all swapping does!

C C++
#include <stdio.h>
int main() {
    int a = 5, b = 10, temp;
    temp = a;
    a = b;
    b = temp;
    printf("a = %d, b = %d\n", a, b);
    return 0;
}
#include <iostream>
using namespace std;
int main() {
    int a = 5, b = 10;
    swap(a, b); // STL swap
    cout << "a = " << a << ", b = " <<
                 b << endl;
    return 0;
}
Java Python
public class SwapExample {
    public static void main(String[] args) {
        int a = 5, b = 10;
        int temp = a;
        a = b;
        b = temp;
        System.out.println("a = " + a + 
                ", b = " + b);
    }
}
a, b = 5, 10
a, b = b, a
print("a =", a, "b =", b)
Rust
fn main() {
    let (mut a, mut b) = (5, 10);
    std::mem::swap(&mut a, &mut b);
    println!("a = {}, b = {}", a, b);
}

🏷️ Comparison Commentary

  • C & Java: Require a manual temporary variable — more boilerplate.
  • C++: Provides swap() in the STL, but unsafe changes are still possible if not careful.
  • Python: Extremely concise with tuple unpacking — hides memory details.
  • Rust: Similar to C++’s swap(), but enforces explicit mutability (mut) and safe borrowing (&mut). Accidental modifications are prevented at compile time.

🦀 Rust Concept Highlight

  • Explicit Mutability (mut): Variables must be declared mutable to be changed.
  • Borrowing with &mut: Rust ensures safe access without copying.
  • std::mem::swap: Safe, zero-cost swapping without manual temp variables.

💡 Try it yourself:
Can you rewrite the Rust swap using tuple destructuring like Python does? Compare which approach feels safer and why.


◀️ Palindrome Check

Like reading a word in a mirror — if it stays the same, it’s a palindrome!

C C++
#include <stdio.h>
#include <string.h>
int main() {
    char str[100], rev[100];
    printf("Enter a string: ");
    scanf("%s", str);

    int len = strlen(str);
    for (int i = 0; i < len; i++)
        rev[i] = str[len - i - 1];
    rev[len] = '\0';

    if (strcmp(str, rev) == 0)
        printf("Palindrome\n");
    else
        printf("Not Palindrome\n");
    return 0;
}
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
    string str;
    cout << "Enter a string: ";
    cin >> str;

    string rev = str;
    reverse(rev.begin(), rev.end());

    if (str == rev)
        cout << "Palindrome" << endl;
    else
        cout << "Not Palindrome" << endl;
    return 0;

}
Java Python
import java.util.*;
class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        String rev = new StringBuilder(str)
                .reverse().toString();
        if (str.equals(rev))
            System.out.println("Palindrome");
        else
            System.out.println("Not Palindrome");
    }
}
str1 = input("Enter string: ")
if str1 == str1[::-1]:
    print("Palindrome")
else:
    print("Not Palindrome")
Rust
use std::io;
fn main() {
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    let input = input.trim();
    let rev: String = input.chars().rev().collect();

    if input == rev {
        println!("Palindrome");
    } else {
        println!("Not Palindrome");
    }
}

🏷️ Comparison Commentary

  • C: Manual reversal using loops — simple but prone to buffer handling issues.
  • C++: Cleaner with reverse() from STL, still manages memory manually.
  • Java: Uses StringBuilder.reverse() — easy and safe, though verbose.
  • Python: One-liner slicing [::-1] makes it minimalistic.
  • Rust: Combines iterators .chars().rev().collect() — safe, Unicode-aware, and expressive.

🦀 Rust Concept Highlight

  • String Iterators: .chars() safely handles each Unicode character.
  • Ownership Safety: No manual copying — collect() builds a new String cleanly.
  • Immutable Input: trim() ensures input is clean before comparison.

💡 Try it yourself:
Make the Rust version case-insensitive using to_lowercase(). Bonus: Try checking sentences like "Never odd or even" — can you ignore spaces?


❕Factorial of a Number

Think of factorial as a countdown where each number shakes hands with all those before it — that’s 5 × 4 × 3 × 2 × 1!

C C++
#include <stdio.h>
int main() {
    int n, fact = 1;
    printf("Enter a number: ");
    scanf("%d", &n);

    for (int i = 1; i <= n; i++)
        fact *= i;
    printf("Factorial = %d\n", fact);
    return 0;
}
#include <iostream>
using namespace std;
int main() {
    int n, fact = 1;
    cout << "Enter a number: ";
    cin >> n;

    for (int i = 1; i <= n; i++)
        fact *= i;
    cout << "Factorial = " << fact << endl;
    return 0;
}
Java Python
import java.util.*;
class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int fact = 1;
        for (int i = 1; i <= n; i++)
            fact *= i;
        System.out.println("Factorial = " + fact);
    }
}
n = int(input("Enter a number: "))
fact = 1
for i in range(1, n + 1):
    fact *= i
print("Factorial =", fact)
Rust
use std::io;
fn main() {
    let mut input = String::new();
    println!("Enter a number:");
    io::stdin().read_line(&mut input).unwrap();
    let n: u32 = input.trim().parse().unwrap();

    let mut fact: u32 = 1;
    for i in 1..=n {
        fact *= i;
    }
    println!("Factorial = {}", fact);
}

🏷️ Comparison Commentary

  • C, C++, Java: Use standard loops; risk of overflow if input is too large.
  • Python: Handles large integers automatically — fewer worries about limits.
  • Rust: Requires type clarity (u32), ensuring safety and predictable integer behavior.

🦀 Rust Concept Highlight

  • Strong Typing: u32 defines unsigned 32-bit integer — prevents negative inputs.
  • Range Syntax: 1..=n elegantly covers all numbers including n.
  • Error Handling: parse().unwrap() converts input safely, but panics on invalid input — you can handle it gracefully using match.

💡 Try it yourself:
Try rewriting the Rust version using recursion instead of a loop. Bonus: Can you use Iterator::product() to make it a one-liner?


🪜 Largest Element in an Array

Imagine checking which student scored the highest in class — that’s finding the largest element!

C C++
#include <stdio.h>
int main() {
    int n;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    int arr[n];
    printf("Enter elements: ");
    for(int i = 0; i < n; i++)
        scanf("%d", &arr[i]);

    int max = arr[0];
    for(int i = 1; i < n; i++)
        if(arr[i] > max)
            max = arr[i];
    printf("Largest element = %d\n", max);
    return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
    int n;
    cout << "Enter number of elements: ";
    cin >> n;
    vector<int> arr(n);
    cout << "Enter elements: ";
    for(int i = 0; i < n; i++)
        cin >> arr[i];

    int max = arr[0];
    for(int i = 1; i < n; i++)
        if(arr[i] > max)
            max = arr[i];
    cout << "Largest element = " << max << endl;
    return 0;
}
Java Python
import java.util.*;
class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n];
        for(int i=0; i<n; i++)
            arr[i] = sc.nextInt();

        int max = arr[0];
        for(int i=1; i<n; i++)
            if(arr[i] > max)
                max = arr[i];
        System.out.println("Largest element = " 
                    + max);
    }
}
n = int(input("Enter number of elements: "))
arr = list(map(int, input("Enter elements: ").split()))

max_val = arr[0]
for num in arr[1:]:
    if num > max_val:
        max_val = num
print("Largest element =", max_val)
Rust
use std::io;
fn main() {
    let mut input = String::new();
    println!("Enter number of elements:");
    io::stdin().read_line(&mut input).unwrap();
    let n: usize = input.trim().parse().unwrap();

    let mut arr = Vec::new();
    println!("Enter elements:");
    input.clear();
    io::stdin().read_line(&mut input).unwrap();
    arr = input.trim().split_whitespace().map(|x| x.parse::<i32>().unwrap()).collect();

    let mut max = arr[0];
    for &num in &arr[1..] {
        if num > max {
            max = num;
        }
    }
    println!("Largest element = {}", max);
}

🏷️ Comparison Commentary

  • C, C++, Java: Manual indexing of arrays — prone to off-by-one errors if not careful.
  • Python: Uses list slicing and iteration — concise and safe.
  • Rust: Uses Vec and safe iteration; prevents out-of-bounds access at compile time.

🦀 Rust Concept Highlight

  • Vec Collection: Dynamic array type — safer than C arrays.
  • Borrowing & Iteration: for &num in &arr avoids copying while safely reading elements.
  • Parse & Collect: Converts strings to integers safely in one line.

💡 Try it yourself:
Can you rewrite the Rust version using arr.iter().max() to find the largest element in a single line? Compare readability and safety with the loop version.


🔢 Matrix Multiplication

Think of multiplying two score sheets — subjects × students — to find everyone’s total performance!

C C++
#include <stdio.h>
int main() {
    int a[5][5], b[5][5], c[5][5];
    int r1, c1, r2, c2;

    printf("Enter rows and columns of matrix A (max 5): ");
    scanf("%d %d", &r1, &c1);
    printf("Enter rows and columns of matrix B (max 5): ");
    scanf("%d %d", &r2, &c2);

    if (c1 != r2) {
        printf("Matrix multiplication not possible!\n");
        return 0;
    }

    printf("Enter elements of matrix A:\n");
    for (int i = 0; i < r1; i++)
        for (int j = 0; j < c1; j++)
            scanf("%d", &a[i][j]);

    printf("Enter elements of matrix B:\n");
    for (int i = 0; i < r2; i++)
        for (int j = 0; j < c2; j++)
            scanf("%d", &b[i][j]);

    for (int i = 0; i < r1; i++)
        for (int j = 0; j < c2; j++) {
            c[i][j] = 0;
            for (int k = 0; k < c1; k++)
                c[i][j] += a[i][k] * b[k][j];
        }

    printf("Resultant Matrix:\n");
    for (int i = 0; i < r1; i++) {
        for (int j = 0; j < c2; j++)
            printf("%d ", c[i][j]);
        printf("\n");
    }

    return 0;
}
#include <iostream>
using namespace std;
int main() {
    int r1,c1,r2,c2;
    cout << "Enter rows and columns of matrix A (max 5): ";
    cin >> r1 >> c1;
    cout << "Enter rows and columns of matrix B (max 5): ";
    cin >> r2 >> c2;
    if(c1!=r2) return 0;

    int A[5][5], B[5][5], C[5][5];

    cout << "Enter elements of matrix A:\n";
    for(int i=0;i<r1;i++) for(int j=0;j<c1;j++) cin >> A[i][j];

    cout << "Enter elements of matrix B:\n";
    for(int i=0;i<r2;i++) for(int j=0;j<c2;j++) cin >> B[i][j];

    for(int i=0;i<r1;i++)
      for(int j=0;j<c2;j++) {
        C[i][j]=0;
        for(int k=0;k<c1;k++) C[i][j]+=A[i][k]*B[k][j];
      }

    cout << "Resultant Matrix:\n";
    for(int i=0;i<r1;i++) {
      for(int j=0;j<c2;j++) cout << C[i][j] << " ";
      cout << endl;
    }
}
Java Python
import java.util.*;
class Main {
    public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
        System.out.print("Enter rows and columns of matrix A: ");
        int r1 = sc.nextInt(), c1 = sc.nextInt();
        System.out.print("Enter rows and columns of matrix B: ");
        int r2 = sc.nextInt(), c2 = sc.nextInt();
        if(c1!=r2) return;

        int[][] A=new int[r1][c1];
        int[][] B=new int[r2][c2];
        int[][] C=new int[r1][c2];

        System.out.println("Enter elements of matrix A:");
        for(int i=0;i<r1;i++) for(int j=0;j<c1;j++) {
            A[i][j] = sc.nextInt();}
        System.out.println("Enter elements of matrix B:");
        for(int i=0;i<r2;i++) for(int j=0;j<c2;j++) {
            B[i][j] = sc.nextInt();}

        for(int i=0;i<r1;i++) for(int j=0;j<c2;j++)
            for(int k=0;k<c1;k++) C[i][j]+=A[i][k]*B[k][j];

        System.out.println("Resultant matrix is: ");
        for(int i=0;i<r1;i++) { 
            for(int j=0;j<c2;j++){
            System.out.print(C[i][j] + " ");
            }
            System.out.println();
        }
    }
}
r1,c1=map(int,input("Enter rows and columns of matrix A: ").split())
r2,c2=map(int,input("Enter rows and columns of matrix B: ").split())

if c1!=r2: exit()
print("Enter elements of matrix A:")
A=[list(map(int,input().split())) for _ in range(r1)]
print("Enter elements of matrix B:")
B=[list(map(int,input().split())) for _ in range(r2)]

C=[[sum(A[i][k]*B[k][j] for k in range(c1)) for j in range(c2)] for i in range(r1)]
print("Resultant matrix is: ")
for row in C: print(*row)
Rust
use std::io;
fn main() {
      let mut buf=String::new();
    println!("Enter rows and columns of matrix A:");
    io::stdin().read_line(&mut buf).unwrap();
    let dims: Vec<usize> = buf.split_whitespace().map(|x| x.parse().unwrap()).collect();
    let (r1,c1) = (dims[0], dims[1]);

    buf.clear();
    println!("Enter rows and columns of matrix B:");
    io::stdin().read_line(&mut buf).unwrap();
    let dims: Vec<usize> = buf.split_whitespace().map(|x| x.parse().unwrap()).collect();
    let (r2,c2) = (dims[0], dims[1]);

    if c1!=r2 { println!("Invalid size!"); return; }

    let mut a = vec![vec![0; c1]; r1];
    let mut b = vec![vec![0; c2]; r2];
    let mut c = vec![vec![0; c2]; r1];

    println!("Enter elements of matrix A:");
    for i in 0..r1 {
        buf.clear();
        io::stdin().read_line(&mut buf).unwrap();
        a[i] = buf.split_whitespace().map(|x| x.parse().unwrap()).collect();
    }

    println!("Enter elements of matrix B:");
    for i in 0..r2 {
        buf.clear();
        io::stdin().read_line(&mut buf).unwrap();
        b[i] = buf.split_whitespace().map(|x| x.parse().unwrap()).collect();
    }

    for i in 0..r1 {
        for j in 0..c2 {
            for k in 0..c1 {
                c[i][j] += a[i][k]*b[k][j];
            }
        }
    }

    println!("Resultant Matrix:");
    for row in &c {
        for val in row{
            print!("{} ", val);
        }
        println!();
    }
}

🏷️ Comparison Commentary

  • C/C++: Fast but needs manual array size checks; prone to errors if exceeded.
  • Java: Safe and structured but more verbose.
  • Python: Compact, readable, and easy for quick experiments.
  • Rust: Combines C’s performance with memory safety; vectors handle dynamic input safely with ownership rules.

🦀 Rust Concept Highlight

  • Ownership & Borrowing: Prevents dangling references and ensures valid memory usage.
  • Vectors (Vec<Vec<i32>>): Safe, dynamic 2D arrays.
  • Input parsing: Reads and converts strings into numbers safely with parse().

💡 Try it yourself:
Try rewriting this Rust code using iterators or map functions instead of nested loops — can you make it more functional while keeping readability?


📝 Conclusion

From these 5 simple programs, we saw how Rust uses methods like std::mem::swap, rev(), fold(), iter().max(), and nested vectors — blending C’s performance, Python’s clarity, and Java’s structure, while adding its own magic of ownership, mutability control, and compile-time safety.

Before we move on to complex systems, this Rust refresher reminds us where it all begins — understanding how a language thinks.

Next on Techn0tz 🚀 → Continue developing with the Teacher Assistant App: Level 3. Stay tuned!

Previous: Level 2 Rust GUI - Enhance Teacher Assistant App with Attendance, Grades, and Reports | Up: Home
Enjoyed this post? Rate it!