diff --git a/C/p076.c b/C/p076.c index 588097d..f412820 100644 --- a/C/p076.c +++ b/C/p076.c @@ -12,23 +12,29 @@ How many different ways can one hundred be written as a sum of at least two posi #include #include #include - -int count(int value, int n, int i); - -int integers[99]; +#include "projecteuler.h" int main(int argc, char **argv) { int i, n; + long int *partitions; double elapsed; struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); - for(i = 0; i < 99; i++) - integers[i] = i + 1; + if((partitions = (long int *)calloc(100, sizeof(long int))) == NULL) + { + fprintf(stderr, "Error while allocating memory\n"); + return 1; + } - n = count(0, 0, 0); + /* The number of ways a number can be written as a sum is given by the partition function + * (-1 because the partition function includes also the number itself). + * The function is implemented in projecteuler.c*/ + n = partition_fn(100, partitions) - 1; + + free(partitions); clock_gettime(CLOCK_MONOTONIC, &end); @@ -41,29 +47,3 @@ int main(int argc, char **argv) return 0; } - -int count(int value, int n, int i) -{ - int j; - - for(j = i; j < 99; j++) - { - value += integers[j]; - - if(value == 100) - { - return n + 1; - } - else if(value > 100) - { - return n; - } - else - { - n = count(value, n, j); - value -= integers[j]; - } - } - - return n; -} diff --git a/C/projecteuler.c b/C/projecteuler.c index c7a0c22..fcf63d8 100644 --- a/C/projecteuler.c +++ b/C/projecteuler.c @@ -783,3 +783,45 @@ int phi(int n, int *primes) return (int)ph; } + +/* Function implementing the partition function.*/ +long int partition_fn(int n, long int *partitions) +{ + int k, limit; + long int res = 0; + + /* The partition function for negative numbers is 0 by definition.*/ + if(n < 0) + { + return 0; + } + + /* The partition function for zero is 1 by definition.*/ + if(n == 0) + { + partitions[n] = 1; + return 1; + } + + /* If the partition for the current n has already been calculated, return the value.*/ + if(partitions[n] != 0) + { + return partitions[n]; + } + + k = -ceil((sqrt(24*n+1)-1)/6); + limit = floor((sqrt(24*n+1)+1)/6); + + while(k <= limit) + { + if(k != 0) + { + res += pow(-1, k+1) * partition_fn(n-k*(3*k-1)/2, partitions); + } + k++; + } + + partitions[n] = res; + + return res; +} diff --git a/C/projecteuler.h b/C/projecteuler.h index a8315b3..ed1ef18 100644 --- a/C/projecteuler.h +++ b/C/projecteuler.h @@ -24,5 +24,6 @@ int pell_eq(int i, mpz_t x); int is_semiprime(int n, int *p, int *q, int *primes); int phi_semiprime(int n, int p, int q); int phi(int n, int *primes); +long int partition_fn(int n, long int *partitions); #endif diff --git a/Python/p075.py b/Python/p075.py index 0a83f43..e4185fb 100644 --- a/Python/p075.py +++ b/Python/p075.py @@ -68,7 +68,6 @@ def main(): if l[i] == 1: count = count + 1 - end = default_timer() print('Project Euler, Problem 75') diff --git a/Python/p076.py b/Python/p076.py new file mode 100644 index 0000000..e597855 --- /dev/null +++ b/Python/p076.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +from timeit import default_timer +from projecteuler import partition_fn + +def main(): + start = default_timer() + + partitions = [0] * 101 + +# The number of ways a number can be written as a sum is given by the partition function +# (-1 because the partition function includes also the number itself). +# The function is implemented in projecteuler.py. + n = partition_fn(100, partitions) - 1 + + end = default_timer() + + print('Project Euler, Problem 76') + print('Answer: {}'.format(n)) + + print('Elapsed time: {:.9f} seconds'.format(end - start)) + +if __name__ == '__main__': + main() diff --git a/Python/projecteuler.py b/Python/projecteuler.py index 038a767..00c8461 100644 --- a/Python/projecteuler.py +++ b/Python/projecteuler.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -from math import sqrt, floor, gcd +from math import sqrt, floor, ceil, gcd from numpy import ndarray, zeros @@ -397,3 +397,33 @@ def phi(n, primes): ph = ph * (1 - 1 / n) return ph + +# Function implementing the partition function. +def partition_fn(n, partitions): +# The partition function for negative numbers is 0 by definition. + if n < 0: + return 0 + +# The partition function for zero is 1 by definition. + if n == 0: + partitions[n] = 1 + return 1 + +# If the partition for the current n has already been calculated, return the value. + if partitions[n] != 0: + return partitions[n] + + res = 0 + k = -ceil((sqrt(24*n+1)-1)//6) + limit = floor((sqrt(24*n+1)+1)//6) + + while k <= limit: + if k != 0: + res = res + pow(-1, k+1) * partition_fn(n-k*(3*k-1)//2, partitions) + k = k + 1 + + partitions[n] = res + + return int(res) + +