Skip to content

Instantly share code, notes, and snippets.

@PayasR
Created October 8, 2019 11:58
Show Gist options
  • Save PayasR/454c09ba8ad5bef9ad9f1555c3fa3a26 to your computer and use it in GitHub Desktop.
Save PayasR/454c09ba8ad5bef9ad9f1555c3fa3a26 to your computer and use it in GitHub Desktop.
Fast primes in Rust
// The Scanner template from https://codeforces.com/contest/1168/submission/54903799
#[allow(unused_imports)]
use std::cmp::{min,max};
use std::io::{BufWriter, stdin, stdout, Write};
#[derive(Default)]
struct Scanner {
buffer: Vec<String>
}
impl Scanner {
fn next<T: std::str::FromStr>(&mut self) -> T {
loop {
if let Some(token) = self.buffer.pop() {
return token.parse().ok().expect("Failed parse");
}
let mut input = String::new();
stdin().read_line(&mut input).expect("Failed read");
self.buffer = input.split_whitespace().rev().map(String::from).collect();
}
}
}
// Regular Sieve of Eratosthenes, could be made better using BitVec, using usize for now.
// Good enough for SPOJ problem PRIME1 (and Codechef if they ever allow Rust)
fn sieve(_upper_bound: usize) -> Vec<usize> {
let _sqrt_upper_bound = (_upper_bound as f64).sqrt() as usize;
let mut v = vec![0; _upper_bound];
v[0] = 1;
v[1]=1;
for _i in 2.._sqrt_upper_bound+1 {
if v[_i] == 0 {
for _j in (2*_i.._upper_bound).step_by(_i) {
v[_j] = 1;
}
}
}
let mut primes = Vec::new();
for i in 1.._upper_bound {
if v[i] == 0 {
primes.push(i);
}
}
primes
}
// https://stackoverflow.com/questions/3220907/efficient-algorithm-to-get-primes-between-two-large-numbers
// 1. Use the sieve of eratosthenes to generate all primes below sqrt(1000000000) = ~32 000 in an array primes.
// 2. For each number x between m and n only test if it's prime by testing for divisibility against numbers <= sqrt(x) from the array primes. So for x = 29 you will only test if it's divisibile by 2, 3 and 5.
fn find_primes_between(_l:usize, _r:usize, vec_primes:&Vec<usize>) -> Vec<usize> {
let mut primes = Vec::new();
for _i in _l.._r {
let mut curr_prime = true;
// Handle special cases of numbers being 0, 1 and 2
if (_i != 2 && _i % 2 == 0) || _i == 0 || _i == 1 {
curr_prime = false;
} else {
for _j in vec_primes {
if _j >= &_i {
break;
}
if _i % _j == 0 {
curr_prime = false;
break;
}
}
}
if curr_prime == true {
primes.push(_i);
}
}
primes
}
fn main()
{
let mut scan = Scanner::default();
let out = &mut BufWriter::new(stdout());
let vec_primes = sieve(1, 1000000000_f64.sqrt() as usize);
let n = scan.next::<usize>();
for _i in 0..n {
let _l = scan.next::<usize>();
let _r = scan.next::<usize>();
let v = find_primes_between(_l, _r+1, &vec_primes);
for _j in v {
writeln!(out, "{}", _j);
}
writeln!(out, "");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment