From 202c289d472bdefba4bcdf38a79491ce832eabca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Ortega=20Froysa?= Date: Wed, 5 May 2021 18:17:37 +0200 Subject: [PATCH] Refractored code to handle import files better. --- src/main.rs | 113 ++++++++++++++++++++++++++++++++++++++-------------- src/test.rs | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 30 deletions(-) create mode 100644 src/test.rs diff --git a/src/main.rs b/src/main.rs index 5b43e4c..1589717 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,24 +22,29 @@ use std::fs::File; use std::io::{BufRead, BufReader}; use std::collections::VecDeque; +mod test; + #[derive(StructOpt)] #[structopt(about = "A prime number generator and tester.")] -struct Opt { +struct Opt +{ #[structopt(short, long, help = "Print all found primes")] verbose:bool, #[structopt(short, long, name="FILE", help = "Import prime numbers from FILE")] import:Option, + #[structopt(short, long, help = "Test if n is prime instead of generation")] + test:bool, #[structopt(help = "Ordinal of the prime to generate")] n:usize, } -fn main() { +fn main() +{ let opts = Opt::from_args(); // get the first `n` primes let n = opts.n; - let mut primes:VecDeque = VecDeque::with_capacity(n); - let mut candidate:u64; + let mut primes:VecDeque = VecDeque::new(); if opts.import.is_some() { @@ -51,46 +56,94 @@ fn main() { let aux:u64 = line.parse().unwrap(); primes.push_back(aux); } - - candidate = *primes.back().unwrap() + 2; } - else + + if opts.test { - // first prime - if opts.verbose + let mut res:bool; + if primes.len() == 0 { - println!("{}", 2); + res = test::is_prime(n as u64); } - primes.push_back(2); - candidate = 3; - } - - while primes.len() < n - { - let mut is_prime = true; - let limit = (candidate as f64).sqrt() as u64; - for i in primes.iter().take_while(|x| **x <= limit) + else if primes.back().unwrap() >= &(n as u64) { - if candidate % *i == 0 + res = primes.contains(&(n as u64)); + } + else if primes.back().unwrap() >= &((n as f64).sqrt() as u64) + { + res = test::is_prime_mem(n as u64, &primes) + } + else + { + res = test::is_prime_mem(n as u64, &primes); + if res { - is_prime = false; - break; + res = test::is_prime_f(n as u64, primes.back().unwrap() + 2); } } - - if is_prime + if res { if opts.verbose { - println!("{}", candidate); + println!("true"); } - primes.push_back(candidate); + std::process::exit(0); + } + else + { + if opts.verbose + { + println!("false"); + } + std::process::exit(1); } - candidate += 2; } - - if !opts.verbose + else { - println!("{}", primes.get(n-1).unwrap()); + if primes.len() >= n + { + println!("{}", primes.get(n-1).unwrap()); + } + else + { + let mut candidate:u64; + + if primes.len() == 0 + { + primes.push_back(2); + if opts.verbose + { + println!("{}", 2); + } + candidate = 3; + } + else if primes.len() == 1 + { + candidate = 3; + } + else + { + candidate = *primes.back().unwrap() + 2; + } + + while primes.len() < n + { + if test::is_prime_mem(candidate, &primes) + { + primes.push_back(candidate); + if opts.verbose + { + println!("{}", candidate); + } + } + + candidate += 2; + } + + if !opts.verbose + { + println!("{}", primes.get(n-1).unwrap()); + } + } } } diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..563a60c --- /dev/null +++ b/src/test.rs @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2021 Ortega Froysa, Nicolás + * Author: Ortega Froysa, Nicolás + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use std::collections::VecDeque; + +pub fn is_prime_f(n:u64, b:u64) -> bool +{ + assert_ne!(b, 0); + assert_ne!(b, 1); + + let mut start = b; + if start == 2 + { + if n % 2 == 0 + { + return false; + } + else + { + start += 1; + } + } + else if start % 2 == 0 + { + start += 1; + } + + let limit = (n as f64).sqrt() as u64 + 1; + for i in (start..limit).step_by(2) + { + if n % i == 0 + { + return false; + } + } + return true; +} + +pub fn is_prime(n:u64) -> bool +{ + return is_prime_f(n, 2); +} + +pub fn is_prime_mem(n:u64, primes:&VecDeque) -> bool +{ + let limit = (n as f64).sqrt() as u64; + for i in primes.iter().take_while(|x| **x <= limit) + { + if n % *i == 0 + { + return false; + } + } + return true; +}