Last active
January 2, 2016 01:39
-
-
Save yomimono/8231546 to your computer and use it in GitHub Desktop.
An implementation of the Sieve of Eratosthenes, which answers the the question "what is the nth prime?", as long as n is <= 10001.
This file contains 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
CFLAGS = -g -Wall | |
all : problem_7 | |
problem_7 : problem_7.c | |
$(CC) $(CFLAGS) -o $@ $< -lm |
This file contains 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
#include <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
unsigned long get_next_prime(unsigned long floor, unsigned long* primes, size_t primes_size) { | |
unsigned int i; | |
unsigned short found_i; | |
found_i = 0; | |
for(i = 0; i < primes_size; i++) { | |
if(floor == primes[i]) { | |
found_i = 1; | |
} else if(found_i == 1 && primes[i] != 0) return primes[i]; | |
} | |
return 0; | |
} | |
unsigned long* sieve_primes(unsigned long max_number, unsigned int* primes_returned) { | |
unsigned long* primes; | |
unsigned long remove_multiples_of; | |
unsigned long ceiling; | |
unsigned int prime_index; | |
*primes_returned = 0; | |
if(max_number == 0 || max_number == 1) { | |
return NULL; | |
} | |
primes = calloc(max_number, sizeof(unsigned long)); | |
memset(primes, 0x00, sizeof(unsigned long) * max_number); | |
//just precalculate extremely trivial cases | |
if(max_number == 2) { | |
primes[0] = 2; | |
(*primes_returned)++; | |
return primes; | |
} | |
if(max_number <= 3) { | |
primes[1] = 3; | |
(*primes_returned)++; | |
return primes; | |
} | |
//figure out the highest number we should bother removing multiples of | |
ceiling = (int) round(sqrt((double)(max_number))); | |
//populate primes with all the numbers from 2 to max_number, inclusive | |
for(prime_index = 0; prime_index < max_number - 1; prime_index++) { | |
primes[prime_index] = prime_index + 2; | |
} | |
primes[prime_index + 1] = 0; | |
//zero out multiples of two, then continue on from there until ceiling is hit | |
for(remove_multiples_of = 2; remove_multiples_of <= ceiling && remove_multiples_of != 0; ) { | |
for(prime_index = 0; prime_index < max_number - 1; prime_index++) { | |
if(primes[prime_index] > remove_multiples_of) { | |
if(primes[prime_index] % remove_multiples_of == 0) primes[prime_index] = 0; | |
} | |
} | |
remove_multiples_of = get_next_prime(remove_multiples_of, primes, max_number); | |
} | |
*primes_returned = max_number; | |
return primes; | |
} | |
unsigned long get_nth_prime(unsigned long n) { | |
unsigned long max; | |
unsigned long* primes; | |
unsigned int primes_returned, counter; | |
unsigned long this_prime; | |
if(n == 0) return 0; | |
if(n == 1) return 2; | |
max = 105000; | |
primes = sieve_primes(max, &primes_returned); | |
if(primes == NULL) return 0; | |
this_prime = 2; | |
counter = 1; | |
do { | |
counter++; | |
this_prime = get_next_prime(this_prime, primes, primes_returned); | |
} while(counter < n && this_prime != 0) ; | |
free(primes); | |
return this_prime; | |
} | |
//input - the number of primes which you wish to calculate | |
//output - a newline-delimited series of primes | |
int main(int argc, char* argv[]) { | |
unsigned long number_of_primes = 0; | |
if(argc < 2) return 1; | |
number_of_primes = strtoul(argv[1], NULL, 10); | |
if(number_of_primes == 0) return 0; | |
printf("%lu\n", get_nth_prime(number_of_primes)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment