Automate The Boring Stuff With Rust
Have you heard of “Automate the Boring Stuff with Python”? Well, that’s exactly how you should approach learning Rust too!
The Learning Dilemma
When learning a new programming language, we often follow a familiar path: reading books, following blogs, and watching video tutorials. However, many of us end up in the same situation — we understand the concepts but struggle to write actual programs in the new language.
This is where the approach of “Automate the Boring Stuff with Python” shines. The book’s secret sauce? Practice Projects at the end of every chapter that ensure readers truly grasp concepts before moving forward.
The Challenge
In this series, we’ll tackle every Practice Project from “Automate the Boring Stuff with Python” — but with a twist. We’ll implement each project in both Python and Rust, comparing their performance along the way.
Prerequisites
Before starting, make sure you:
- Complete Chapters 1 and 2 in the official Rust Book
- Have basic Python knowledge
- Set up your Rust development environment
Project #1: The Collatz Sequence
Let’s start with the first practice project from Chapter 3 (Functions).
The Problem
Create a function collatz()
that takes a number and follows these rules:
- If the number is even, divide it by 2
- If the number is odd, multiply it by 3 and add 1
- Continue this process until reaching 1
Implementation
Here’s our Rust solution with error handling and performance timing:
Solution:
use std::io;
use std::time::Instant;
fn collatz(number: i64) -> i64 {
if number % 2 == 0 {
number / 2
} else {
3 * number + 1
}
}
fn timed_collatz_sequence() {
loop {
println!("Enter number: ");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
match input.trim().parse() {
Ok(mut number) => {
let start_time = Instant::now();
while number != 1 {
number = collatz(number);
println!("{}", number);
}
let elapsed_time = start_time.elapsed();
println!("Time taken: {:.6} seconds", elapsed_time.as_secs_f64());
break;
}
Err(_) => {
println!("Error: You must enter an integer.");
println!("Please try again.");
}
}
}
}
fn main() {
timed_collatz_sequence();
}
import time
def collatz(number):
if number % 2 == 0:
result = number // 2
else:
result = 3 * number + 1
print(result)
return result
def timed_collatz_sequence():
while True:
try:
number = int(input("Enter number: "))
start_time = time.time()
while number != 1:
number = collatz(number)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Time taken: {elapsed_time:.6f} seconds")
break # Exit the loop if successful
except ValueError:
print("Error: You must enter an integer.")
print("Please try again.")
# Run the timed callatz function
timed_collatz_sequence()
when running the program 3 times for the Rust and 3 times for the python script with the number 5 as the input.
Language Average Speed (seconds):
Python: 0.0001293
Rust: 0.0000337
Rust is 3.84 times faster
Links:
Next up:
Chapter 4: Lists and Grids — Where Performance Gets Serious
After warming up with basic functions, we’re diving into lists and grids — and this is where Rust’s performance advantages become more pronounced. While our Collatz sequence with simple calculations showed modest gains, working with data structures reveals Rust’s true strengths.
Why The Speed Boost?
The performance gap widens here due to Rust’s:
- Efficient stack memory usage
- Zero-cost grid operations
- Cache-friendly data layouts
- Predictable memory patterns
- No garbage collection overhead
We’ll tackle two challenges:
- Character Picture Grid: Rotating character grids 90 degrees
- Comma Code: Converting lists into natural language strings
Each project will demonstrate how Rust’s strict memory model and efficient data structure handling lead to significant performance improvements over Python — often orders of magnitude faster when working with larger datasets.
Ready to see Rust flex its muscles? Let’s dive into the code!
Would you like me to continue with the implementation details of either challenge?