Add comments

Added comments to the C code for all the problems solved so far.
This commit is contained in:
daniele 2019-09-26 11:38:04 +02:00
parent 9df4d3fe97
commit ecdbadba7e
Signed by: fuxino
GPG Key ID: 6FE25B4A3EE16FDA
10 changed files with 153 additions and 65 deletions

View File

@ -10,8 +10,6 @@
#include <time.h>
#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);
}

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -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;

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -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;

View File

@ -1,3 +1,12 @@
/* Pentagonal numbers are generated by the formula, Pn=n(3n1)/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 <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -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;

View File

@ -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(3n1)/2 1, 5, 12, 22, 35, ...
* Hexagonal H_n=n(2n1) 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 <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -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))

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -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)

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -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);

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -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);

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <math.h>
@ -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])
{

View File

@ -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__':