diff --git a/C/p021.c b/C/p021.c index 5fe230a..e39ec2e 100644 --- a/C/p021.c +++ b/C/p021.c @@ -24,10 +24,10 @@ int main(int argc, char **argv) { /* Calculate the sum of proper divisors with the function * implemented in projecteuler.c.*/ - n = sum_of_divisors(i); + n = sum_of_divisors(i, 1); /* If i!=n and the sum of proper divisors of n=i, * sum the pair of numbers and add it to the total.*/ - if(i != n && sum_of_divisors(n) == i) + if(i != n && sum_of_divisors(n, 1) == i) { sum += i + n; } diff --git a/C/p023.c b/C/p023.c index 247e9fe..c46d3b4 100644 --- a/C/p023.c +++ b/C/p023.c @@ -84,5 +84,5 @@ int main(int argc, char **argv) int is_abundant(int n) { - return sum_of_divisors(n) > n; + return sum_of_divisors(n, 1) > n; } diff --git a/C/p095.c b/C/p095.c index cd96384..b581ec2 100644 --- a/C/p095.c +++ b/C/p095.c @@ -16,20 +16,18 @@ #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 sociable_chain(int i, int *chain, int l, int *min); -/* 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 main(int argc, char **argv) { int i, min = 0, min_tmp, length, l_max = 0; + int chain[100]; double elapsed; struct timespec start, end; @@ -39,14 +37,14 @@ int main(int argc, char **argv) { /* 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) + if((divisors[i] = sum_of_divisors(i, 1)) == i) { continue; } else { min_tmp = i; - length = sociable_chain(i, i, &min_tmp, 0); + length = sociable_chain(i, chain, 0, &min_tmp); } if(length > l_max) @@ -68,38 +66,15 @@ int main(int argc, char **argv) return 0; } -int sum_proper_divisors(int n) -{ - int i, limit, sum = 1; - - limit = floor(sqrt(n)); - - for(i = 2; i <= limit; i++) - { - if(n % i == 0) - { - sum += i; - sum += n / i; - } - } - - if(n == limit * limit) - { - sum -= limit; - } - - return sum; -} - /* Function to recursively find the length of the chain.*/ -int sociable_chain(int i, int start, int *min, int l) +int sociable_chain(int i, int *chain, int l, int *min) { int n; /* Save current number in the chain.*/ - c[l] = i; + chain[l] = i; - /* If we reached 1, the chain will never return go anywhere.*/ + /* If we reached 1, the chain will never go anywhere.*/ if(i == 1) { return -1; @@ -112,7 +87,7 @@ int sociable_chain(int i, int start, int *min, int l) } else { - n = sum_proper_divisors(i); + n = sum_of_divisors(i, 1); divisors[i] = n; } @@ -123,7 +98,7 @@ int sociable_chain(int i, int start, int *min, int l) } /* If the next number in the chain is equal to the starting one, the chain is finished.*/ - if(n == start) + if(n == chain[0]) { return l + 1; } @@ -132,7 +107,7 @@ int sociable_chain(int i, int start, int *min, int l) * chain is stuck in a loop that will not return to the starting number.*/ for(i = l; i > 0; i--) { - if(n == c[i]) + if(n == chain[i]) { return -1; } @@ -145,5 +120,5 @@ int sociable_chain(int i, int start, int *min, int l) *min = n; } - return sociable_chain(n, start, min, l+1); + return sociable_chain(n, chain, l+1, min); } diff --git a/C/projecteuler.c b/C/projecteuler.c index e1e7de8..e8f1959 100644 --- a/C/projecteuler.c +++ b/C/projecteuler.c @@ -238,7 +238,7 @@ int find_max_path(int **triang, int n) return triang[0][0]; } -int sum_of_divisors(int n) +int sum_of_divisors(int n, int proper) { int i, sum = 1, limit; @@ -254,14 +254,21 @@ int sum_of_divisors(int n) if(n % i == 0) { sum += i; - /* If n is a perfect square, i=limit is a divisor and - * has to be counted only once.*/ - if(n != i * i) - { - sum += (n / i); - } + sum += n / i; } } + + /* If n is a perfect square, i=limit is a divisor and + * has to be counted only once.*/ + if(n == limit * limit) + { + sum -= limit; + } + + if(!proper) + { + sum += n; + } return sum; } diff --git a/C/projecteuler.h b/C/projecteuler.h index cd2d396..1ed43c6 100644 --- a/C/projecteuler.h +++ b/C/projecteuler.h @@ -12,7 +12,7 @@ long int lcmm(long int *values, int n); int *sieve(int n); int count_divisors(int n); int find_max_path(int **triang, int n); -int sum_of_divisors(int n); +int sum_of_divisors(int n, int proper); void swap(void **vet, int i, int j); void insertion_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv)); void quick_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv));