This is a basic command line program that, given a number, returns a list of primes up to and including that number. Also handles a lack of command line arguments and non-number arguments.
I ran into a bunch of problems with Option
s while I was writing this, which led to me using unwrap()
out of desperation. I'd rather never use unwrap
, and instead handle None
or Err
or whatever. Additionally, I'd prefer not to have everything so mut
able.
// A bad implementation of the Sieve of Eratosthenes
// Usage:
// primesTo x = comma-separated list of all primes up to x
use std::env;
// Returns a vector of primes from 2 to max
fn primes_to(max: u32) -> Vec<u32> {
let mut all: Vec<u32> = (2..max+1).collect();
let mut primes: Vec<u32> = vec!();
while all.len() > 0 {
let (a, b) = sieve(all, primes);
all = a;
primes = b;
}
primes
}
// Sieve a non-empty list
fn sieve(list: Vec<u32>, mut primes: Vec<u32>) -> (Vec<u32>, Vec<u32>) {
// We have a Vec<u32>
// We want a u32 and a Vec<u32>
let mut i_list = list.into_iter();
let head: u32 = i_list.next().unwrap();
let mut tail: Vec<u32> = i_list.collect();
tail.retain(|&x| x % head != 0);
primes.push(head);
(tail, primes)
}
fn prettyprint_primes(mut primes: Vec<u32>) -> () {
let temp = primes.pop().unwrap();
for prime in primes {
print!("{:}, ", prime);
}
print!("{:}", temp);
}
fn main() {
let args: Vec<String> = env::args().collect();
let arg: Option<&String> = args.get(1);
match arg {
None => {
println!("Please enter a number to receive primes.");
println!("Usage:");
println!("\ttoPrime x");
},
Some(x) => {
match x.parse::<u32>() {
Ok(max) => {
let primes: Vec<u32> = primes_to(max);
prettyprint_primes(primes);
},
_ => println!("That's not a number; please enter a number"),
}
}
}
}