Improve solution for problem 95

This commit is contained in:
daniele 2019-10-02 11:41:38 +02:00
parent d8d6d56633
commit e7f8e6f633
Signed by: fuxino
GPG Key ID: 6FE25B4A3EE16FDA

View File

@ -21,7 +21,7 @@
#define N 1000000 #define N 1000000
int sum_proper_divisors(int i); int sum_proper_divisors(int i);
int chain(int i, int start, int *min, int l); int sociable_chain(int i, int start, int *min, int l);
int chains[N] = {0}; int chains[N] = {0};
/* Vector to save the current chain values. I started with a longer vector, /* Vector to save the current chain values. I started with a longer vector,
@ -32,7 +32,8 @@ int *primes;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i, min, min_tmp, length, l_max = -1; /* 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;
double elapsed; double elapsed;
struct timespec start, end; struct timespec start, end;
@ -47,7 +48,7 @@ int main(int argc, char **argv)
for(i = 4; i <= N; i++) for(i = 4; i <= N; i++)
{ {
/* Calculate the divisors of i, or retrieve the value if previously calculated. /* Calculate the divisors of i, or retrieve the value if previously calculated.
* If i is equale to the sum of its proper divisors, the length of the chain is 1 * 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.*/ * (i.e. i is a perfect number.*/
if(divisors[i] == i || (divisors[i] = sum_proper_divisors(i)) == i) if(divisors[i] == i || (divisors[i] = sum_proper_divisors(i)) == i)
{ {
@ -57,7 +58,7 @@ int main(int argc, char **argv)
else if(!primes[i]) else if(!primes[i])
{ {
min_tmp = i; min_tmp = i;
length = chain(i, i, &min_tmp, 0); length = sociable_chain(i, i, &min_tmp, 0);
} }
/* If i is prime, 1 is its only proper divisor, so no amicable chain is possible.*/ /* If i is prime, 1 is its only proper divisor, so no amicable chain is possible.*/
else else
@ -110,26 +111,30 @@ int sum_proper_divisors(int n)
return sum; return sum;
} }
int chain(int i, int start, int *min, int l) int sociable_chain(int i, int start, int *min, int l)
{ {
int n; int n;
/* If the value of the chain starting with the current number has already /* If we already calculated that the current value can't form a chain,
* been calculated, return the value.*/ * or has a chain starting from a different number, it can't form a
if(chains[i] > 0) * chain starting with the current number, so just return -1.*/
if(chains[i] != 0)
{ {
return chains[i]; chains[start] = -1;
return -1;
} }
/* If we reached a prime number, the chain will be stuck at 1.*/ /* If we reached a prime number, the chain will never return to the starting number.*/
if(primes[i]) if(primes[i])
{ {
chains[start] = -1;
return -1; return -1;
} }
/* Calculate the divisors of i, or retrieve the value if previously calculated.*/ /* Calculate the divisors of i, or retrieve the value if previously calculated.*/
if(divisors[i] != 0) if(divisors[i] != 0)
{ {
chains[start] = -1;
n = divisors[i]; n = divisors[i];
} }
else else
@ -154,6 +159,7 @@ int chain(int i, int start, int *min, int l)
{ {
if(n == c[i]) if(n == c[i])
{ {
chains[start] = -1;
return -1; return -1;
} }
} }
@ -161,6 +167,7 @@ int chain(int i, int start, int *min, int l)
/* We are looking for chain where no value is greater than 1000000.*/ /* We are looking for chain where no value is greater than 1000000.*/
if(n > N) if(n > N)
{ {
chains[start] = -1;
return -1; return -1;
} }
@ -171,5 +178,5 @@ int chain(int i, int start, int *min, int l)
*min = n; *min = n;
} }
return chain(n, start, min, l+1); return sociable_chain(n, start, min, l+1);
} }