diff --git a/C/p024.c b/C/p024.c index 7c1bd8a..28e2067 100644 --- a/C/p024.c +++ b/C/p024.c @@ -10,8 +10,6 @@ #include #include "projecteuler.h" -void next_perm(int **perm, int n); -void swap(int **vet, int i, int j); int compare(void *a, void *b); int main(int argc, char **argv) @@ -43,7 +41,7 @@ int main(int argc, char **argv) { /* Function that generates permutations in lexicographic order. * Finish when the 1000000th is found.*/ - next_perm(perm, 10); + next_permutation((void **)perm, 10, compare); } for(i = 0; i < 10; i++) @@ -73,15 +71,6 @@ int main(int argc, char **argv) return 0; } -void swap(int **vet, int i, int j) -{ - int *tmp; - - tmp = vet[i]; - vet[i] = vet[j]; - vet[j] = tmp; -} - int compare(void *a, void *b) { int *n1, *n2; @@ -91,38 +80,3 @@ int compare(void *a, void *b) return *n1 - *n2; } - -/* Implements SEPA (Simple, Efficient Permutation Algorithm) - * to find the next permutation.*/ -void next_perm(int **perm, int n) -{ - int i, key; - - /* Starting from the right of the array, for each pair of values - * if the left one is smaller than the right, that value is the key.*/ - for(i = n - 2; i >= 0; i--) - { - if(compare((void *)perm[i], (void *)perm[i+1]) < 0) - { - key = i; - break; - } - } - - /* If no left value is smaller than its right value, the - * array is in reverse order, i.e. it's the last permutation.*/ - if(i == -1) - { - return; - } - - /* Find the smallest value on the right of the key which is bigger than the key itself, - * considering that the values at the right of the key are in reverse order.*/ - for(i = key + 1; i < n && compare((void *)perm[i], (void *)perm[key]) > 0; i++); - - /* Swap the value found and the key.*/ - swap(perm, key, i-1); - /* Sort the values at the right of the key. This is - * the next permutation.*/ - insertion_sort((void **)perm, key+1, n-1, compare); -} diff --git a/C/p041.c b/C/p041.c index ed06c68..348302c 100644 --- a/C/p041.c +++ b/C/p041.c @@ -1,3 +1,8 @@ +/* We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital + * and is also prime. + * + * What is the largest n-digit pandigital prime that exists?*/ + #include #include #include @@ -8,27 +13,34 @@ int count_digits(int n); int main(int argc, char **argv) { - int i, found = 0; + /* 8- and 9-digit pandigital numbers can't be prime, because + * 1+2+...+8=36, which is divisible by 3, and 36+9=45 which is + * also divisible by 3, and therefore the whole number is divisible + * by 3. So we can start from the largest 7-digit pandigital number, + * until we find a prime.*/ + int i = 7654321; double elapsed; struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); - for(i = 7654321; !found && i > 0; i -= 2) + while(i > 0) { - if(is_pandigital(i, count_digits(i)) && is_prime(i)) { - printf("Project Euler, Problem 41\n"); - printf("Answer: %d\n", i); - found = 1; + break; } +// Skipping the even numbers. + i -= 2; } clock_gettime(CLOCK_MONOTONIC, &end); elapsed = (end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1000000000; + printf("Project Euler, Problem 41\n"); + printf("Answer: %d\n", i); + printf("Elapsed time: %.9lf seconds\n", elapsed); return 0; diff --git a/C/p042.c b/C/p042.c index 7b5a828..a6dfe3d 100644 --- a/C/p042.c +++ b/C/p042.c @@ -1,3 +1,13 @@ +/* The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangle numbers are: + * + * 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... + * + * By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. + * For example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word value is a triangle number then we shall call the word a triangle word. + * + * Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, + * how many are triangle words?*/ + #include #include #include @@ -28,6 +38,7 @@ int main(int argc, char **argv) n = 1; len = strlen(line); + /* Count the words.*/ for(i = 0; i < len; i++) { if(line[i] == ',') @@ -42,6 +53,7 @@ int main(int argc, char **argv) return 1; } + /* Save the words in an array of strings.*/ words[0] = strtok(line, ",\""); for(i = 1; i < n; i++) @@ -49,6 +61,7 @@ int main(int argc, char **argv) words[i] = strtok(NULL, ",\""); } + /* For each word, calculate its value and check if it's a triangle number.*/ for(i = 0; i < n; i++) { value = 0; diff --git a/C/p044.c b/C/p044.c index ec35a86..e781902 100644 --- a/C/p044.c +++ b/C/p044.c @@ -1,3 +1,12 @@ +/* Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. The first ten pentagonal numbers are: + * + * 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ... + * + * It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, 70 − 22 = 48, is not pentagonal. + * + * Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference are pentagonal and D = |Pk − Pj| is minimised; + * what is the value of D?*/ + #include #include #include @@ -14,6 +23,9 @@ int main(int argc, char **argv) n = 2; + /* Check all couples of pentagonal numbers until the right one + * is found. Use the function implemented in projecteuler.c to + * check if the sum and difference ot the two numbers is pentagonal.*/ while(!found) { pn = n * (3 * n - 1) / 2; diff --git a/C/p045.c b/C/p045.c index 534086f..e0680d2 100644 --- a/C/p045.c +++ b/C/p045.c @@ -1,3 +1,13 @@ +/* Triangle, pentagonal, and hexagonal numbers are generated by the following formulae: + * + * Triangle T_n=n(n+1)/2 1, 3, 6, 10, 15, ... + * Pentagonal P_n=n(3n−1)/2 1, 5, 12, 22, 35, ... + * Hexagonal H_n=n(2n−1) 1, 6, 15, 28, 45, ... + * + * It can be verified that T_285 = P_165 = H_143 = 40755. + * + * Find the next triangle number that is also pentagonal and hexagonal.*/ + #include #include #include @@ -18,6 +28,9 @@ int main(int argc, char **argv) while(!found) { i++; + /* Hexagonal numbers are also triangle numbers, so it's sufficient + * to generate hexagonal numbers (starting from H_144) and check if + * they're also pentagonal.*/ n = i * (2 * i - 1); if(is_pentagonal(n)) diff --git a/C/p047.c b/C/p047.c index 38a80ff..35cc6f9 100644 --- a/C/p047.c +++ b/C/p047.c @@ -1,3 +1,16 @@ +/* The first two consecutive numbers to have two distinct prime factors are: + * + * 14 = 2 × 7 + * 15 = 3 × 5 + * + * The first three consecutive numbers to have three distinct prime factors are: + * + * 644 = 2² × 7 × 23 + * 645 = 3 × 5 × 43 + * 646 = 2 × 17 × 19. + * + * Find the first four consecutive integers to have four distinct prime factors each. What is the first of these numbers?*/ + #include #include #include @@ -24,7 +37,9 @@ int main(int argc, char **argv) return 1; } - for(i = 645; !found && i < N - 3; i++) + /* Starting from 647, count the distinct prime factors of n, n+1, n+2 and n+3. + * If they all have 4, the solution is found.*/ + for(i = 647; !found && i < N - 3; i++) { if(!primes[i] && !primes[i+1] && !primes[i+2] && !primes[i+3]) { @@ -54,6 +69,8 @@ int count_distinct_factors(int n) { int i, count=0; + /* Start checking if 2 is a prime factor of n. Then remove + * all 2s factore.*/ if(n % 2 == 0) { count++; @@ -64,6 +81,10 @@ int count_distinct_factors(int n) }while(n % 2 == 0); } + /* Check all odd numbers i, if they're prime and they're a factor + * of n, count them and then divide n for by i until all factors i + * are eliminated. Stop the loop when n=1, i.e. all factors have + * been found.*/ for(i = 3; n > 1; i += 2) { if(primes[i] && n % i == 0) diff --git a/C/p048.c b/C/p048.c index 28edb15..774f5ef 100644 --- a/C/p048.c +++ b/C/p048.c @@ -1,3 +1,7 @@ +/* The series, 1^1 + 2^2 + 3^3 + ... + 10^10 = 10405071317. + * + * Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + ... + 1000^1000.*/ + #include #include #include @@ -17,6 +21,7 @@ int main(int argc, char **argv) mpz_init_set_ui(sum, 0); mpz_init(power); + /* Simply calculate the sum of the powers using the GMP Library.*/ for(i = 1; i <= 1000; i++) { mpz_ui_pow_ui(power, i, i); diff --git a/C/p049.c b/C/p049.c index 5d354e7..0bba891 100644 --- a/C/p049.c +++ b/C/p049.c @@ -1,3 +1,11 @@ +/* The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, + * and, (ii) each of the 4-digit numbers are permutations of one another. + * + * There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property, but there is one other 4-digit + * increasing sequence. + * + * What 12-digit number do you form by concatenating the three terms in this sequence?*/ + #include #include #include @@ -12,7 +20,7 @@ int *primes; int main(int argc, char **argv) { - int i, j, found = 0; + int i = 1489, j, found = 0; double elapsed; struct timespec start, end; @@ -24,12 +32,18 @@ int main(int argc, char **argv) return 1; } - for(i = 1489; i < N && !found; i++) + /* Starting from i=1489 (bigger than the first number in the sequence given in the problem), + * check odd numbers. If they're prime, loop on even numbers j (odd+even=odd, odd+odd=even and + * we need odd numbers because we're looking for primes) up to 4254 (1489+2*4256=10001 which has + * 5 digits.*/ + while(i < N) { if(primes[i]) { - for(j = 1; j < 4255; j++) + for(j = 2; j < 4255; j += 2) { + /* If i, i+j and i+2*j are all primes and they have + * all the same digits, the result has been found.*/ if(i + 2 * j < N && primes[i+j] && primes[i+2*j] && check_digits(i, i+j) && check_digits(i, i+2*j)) { @@ -38,6 +52,11 @@ int main(int argc, char **argv) } } } + if(found) + { + break; + } + i += 2; } free(primes); @@ -47,7 +66,7 @@ int main(int argc, char **argv) elapsed = (end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1000000000; printf("Project Euler, Problem 49\n"); - printf("Answer: %d%d%d\n", i-1, i-1+j, i-1+2*j); + printf("Answer: %d%d%d\n", i, i+j, i+2*j); printf("Elapsed time: %.9lf seconds\n", elapsed); diff --git a/C/p050.c b/C/p050.c index aea0414..bc061f0 100644 --- a/C/p050.c +++ b/C/p050.c @@ -1,3 +1,13 @@ +/* The prime 41, can be written as the sum of six consecutive primes: + * + * 41 = 2 + 3 + 5 + 7 + 11 + 13 + * + * This is the longest sum of consecutive primes that adds to a prime below one-hundred. + * + * The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953. + * + * Which prime, below one-million, can be written as the sum of the most consecutive primes?*/ + #include #include #include @@ -21,14 +31,39 @@ int main(int argc, char **argv) return 1; } - for(i = 2; i < N; i++) + /* Starting from a prime i, add consecutive primes until the + * sum exceeds the limit, every time the sum is also a prime + * save the value and the count if the count is larger than the + * current maximum. Repeat for all primes below N. + * A separate loop is used for i=2, so later only odd numbers are + * checked for primality.*/ + i = 2; + count = 1; + sum = i; + + for(j = i + 1; j < N && sum < N; j++) + { + if(primes[j]) + { + sum += j; + count++; + + if(sum < N && primes[sum] && count > max) + { + max = count; + max_p = sum; + } + } + } + + for(i = 3; i < N; i += 2) { if(primes[i]) { count = 1; sum = i; - for(j = i + 1; j < N && sum < N; j++) + for(j = i + 2; j < N && sum < N; j += 2) { if(primes[j]) { diff --git a/Python/p041.py b/Python/p041.py index 0fb3f0e..2219140 100644 --- a/Python/p041.py +++ b/Python/p041.py @@ -15,14 +15,18 @@ def count_digits(n): def main(): start = default_timer() - for i in range(7654321, 0, -2): - if is_pandigital(i, count_digits(i)) and is_prime(i): - print('Project Euler, Problem 41') - print('Answer: {}'.format(i)) - break + i = 7654321 + while(i > 0): + if is_pandigital(i, count_digits(i)) and is_prime(i): + break + i = i - 2 + end = default_timer() + print('Project Euler, Problem 41') + print('Answer: {}'.format(i)) + print('Elapsed time: {:.9f} seconds'.format(end - start)) if __name__ == '__main__':