diff --git a/C/p095.c b/C/p095.c index 248281d..cd96384 100644 --- a/C/p095.c +++ b/C/p095.c @@ -16,57 +16,39 @@ #include #include #include -#include "projecteuler.h" #define N 1000000 int sum_proper_divisors(int i); int sociable_chain(int i, int start, int *min, int l); -int chains[N] = {0}; /* Vector to save the current chain values. I started with a longer vector, * but no chain is longer than 100 elements, so this is sufficient.*/ int c[100]; int divisors[N] = {0}; -int *primes; int main(int argc, char **argv) { - /* l_max starts from 3 because we're interested in chains of at least 3 elements.*/ - int i, min = 0, min_tmp, length, l_max = 2; + int i, min = 0, min_tmp, length, l_max = 0; double elapsed; struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); - if((primes = sieve(N+1)) == NULL) - { - fprintf(stderr, "Error! Sieve function returned NULL\n"); - return 1; - } - for(i = 4; i <= N; i++) { - /* Calculate the divisors of i, or retrieve the value if previously calculated. - * If i is equal to the sum of its proper divisors, the length of the chain is 1 - * (i.e. i is a perfect number.*/ - if(divisors[i] == i || (divisors[i] = sum_proper_divisors(i)) == i) + /* Calculate the divisors of i and save it. Ii is equal to the sum of its proper divisors, + * the length of the chain is 1 and we don't need to check it.*/ + if((divisors[i] = sum_proper_divisors(i)) == i) { - length = 1; - chains[i] = length; + continue; } - else if(!primes[i]) + else { min_tmp = i; length = sociable_chain(i, i, &min_tmp, 0); } - /* If i is prime, 1 is its only proper divisor, so no amicable chain is possible.*/ - else - { - length = -1; - chains[i] = length; - } - + if(length > l_max) { l_max = length; @@ -74,8 +56,6 @@ int main(int argc, char **argv) } } - free(primes); - clock_gettime(CLOCK_MONOTONIC, &end); elapsed = (end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1000000000; @@ -111,30 +91,23 @@ int sum_proper_divisors(int n) return sum; } +/* Function to recursively find the length of the chain.*/ int sociable_chain(int i, int start, int *min, int l) { int n; - /* If we already calculated that the current value can't form a chain, - * or has a chain starting from a different number, it can't form a - * chain starting with the current number, so just return -1.*/ - if(chains[i] != 0) - { - chains[start] = -1; - return -1; - } + /* Save current number in the chain.*/ + c[l] = i; - /* If we reached a prime number, the chain will never return to the starting number.*/ - if(primes[i]) + /* If we reached 1, the chain will never return go anywhere.*/ + if(i == 1) { - chains[start] = -1; return -1; } /* Calculate the divisors of i, or retrieve the value if previously calculated.*/ if(divisors[i] != 0) { - chains[start] = -1; n = divisors[i]; } else @@ -142,35 +115,29 @@ int sociable_chain(int i, int start, int *min, int l) n = sum_proper_divisors(i); divisors[i] = n; } + + /* We are looking for chain where no value is greater than 1000000.*/ + if(n > N) + { + return -1; + } /* If the next number in the chain is equal to the starting one, the chain is finished.*/ if(n == start) { - chains[start] = l + 1; return l + 1; } - /* Save n, i.e. the next value in the chain, and check if it's equal - * to another value of the chain different from start. If it is, the + /* Check if n is equal to another value of the chain different from start. If it is, the * chain is stuck in a loop that will not return to the starting number.*/ - c[l] = n; - - for(i = 0; i < l; i++) + for(i = l; i > 0; i--) { if(n == c[i]) { - chains[start] = -1; return -1; } } - /* We are looking for chain where no value is greater than 1000000.*/ - if(n > N) - { - chains[start] = -1; - return -1; - } - /* If the next value is smaller than the minimum value of the chain, * update the minimum.*/ if(n < *min)