Skip to content

Instantly share code, notes, and snippets.

@yomimono
Last active January 2, 2016 01:39
Show Gist options
  • Save yomimono/8231546 to your computer and use it in GitHub Desktop.
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.
CFLAGS = -g -Wall
all : problem_7
problem_7 : problem_7.c
$(CC) $(CFLAGS) -o $@ $< -lm
#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