Created
October 8, 2019 11:58
-
-
Save PayasR/454c09ba8ad5bef9ad9f1555c3fa3a26 to your computer and use it in GitHub Desktop.
Fast primes in Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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