From 7f64f15e8998245bdcc5901f6ac25a1894845430 Mon Sep 17 00:00:00 2001 From: Daniele Fucini Date: Sun, 22 Sep 2019 17:48:52 +0200 Subject: [PATCH] Add comments Added comments to the code of the first 5 problems in C. --- C/p001.c | 8 ++++- C/p002.c | 12 +++++++- C/p003.c | 33 +++++++++++++++------ C/p004.c | 8 +++++ C/p005.c | 5 ++++ C/projecteuler.c | 67 ++++++++++++++++++++++++++++-------------- C/projecteuler.h | 6 ++-- Python/projecteuler.py | 8 +---- 8 files changed, 104 insertions(+), 43 deletions(-) diff --git a/C/p001.c b/C/p001.c index 2df1027..c5f33e3 100644 --- a/C/p001.c +++ b/C/p001.c @@ -1,3 +1,7 @@ +/* If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. + * + * Find the sum of all the multiples of 3 or 5 below 1000.*/ + #include #include #include @@ -10,7 +14,9 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &start); - for(i = 1; i < 1000; i++) + /* Simple brute-force approach: try every number between 3 and 999, + * check if it's a multiple of 3 or 5, if yes add it to the total.*/ + for(i = 3; i < 1000; i++) { if (i % 3 == 0 || i % 5 == 0) { diff --git a/C/p002.c b/C/p002.c index 2914b78..53a293b 100644 --- a/C/p002.c +++ b/C/p002.c @@ -1,7 +1,15 @@ +/* Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: + * + * 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... + * + * By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.*/ + #include #include #include +#define N 4000000 + int main(int argc, char **argv) { int fib0 = 1, fib1 = 2, fib2, sum = 2; @@ -12,7 +20,9 @@ int main(int argc, char **argv) fib2 = fib0 + fib1; - while(fib2 <= 4000000) + /* Simple brute-force approach: generate every value in the Fibonacci + * sequence smaller than 4 million and if it's even add it to the total.*/ + while(fib2 <= N) { if(fib2 % 2 == 0) { diff --git a/C/p003.c b/C/p003.c index 43df0a8..ccc05a7 100644 --- a/C/p003.c +++ b/C/p003.c @@ -1,20 +1,25 @@ +/* The prime factors of 13195 are 5, 7, 13 and 29. + * + * What is the largest prime factor of the number 600851475143?*/ + #include #include #include #include #include "projecteuler.h" -int max_prime_factor(long int num); +long int max_prime_factor(long int num); int main(int argc, char **argv) { - int res; + long int res; long int num = 600851475143; double elapsed; struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); + /* Use a function to calculate the largest prime factor.*/ res = max_prime_factor(num); clock_gettime(CLOCK_MONOTONIC, &end); @@ -22,41 +27,51 @@ 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 3\n"); - printf("Answer: %d\n", res); + printf("Answer: %ld\n", res); printf("Elapsed time: %.9lf seconds\n", elapsed); return 0; } -int max_prime_factor(long int num) +/* Recursive approach: if num is prime, return num, otherwise + * recursively look for the largest prime factor of num divided + * by its prime factors until only the largest remains.*/ +long int max_prime_factor(long int num) { - int i, limit; + long int i; + /* Use function defined in projecteuler.c to check if a number is prime.*/ if(is_prime(num)) { return num; } + /* If num is even, find the largest prime factor of num/2.*/ if(num % 2 == 0) { return max_prime_factor(num/2); } else { - limit = floor(sqrt(num)); - - for(i = 3; i <= limit; i += 2) + i = 3; + + while(1) { + /* If num is divisible by i and i is prime, find largest prime + * factor of num/i.*/ if(num % i == 0) { - if(is_prime((long int)i)) + if(is_prime(i)) { return max_prime_factor(num/i); } } + + i += 2; } } + /* Should never get here.*/ return -1; } diff --git a/C/p004.c b/C/p004.c index e37f4b6..0703fcb 100644 --- a/C/p004.c +++ b/C/p004.c @@ -1,3 +1,7 @@ +/* A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. + * + * Find the largest palindrome made from the product of two 3-digit numbers.*/ + #include #include #include @@ -11,11 +15,15 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &start); + /* Using a brute-force approach: generate every product of 3-digit numbers + * and check if it's palindrome. If the product found is greater than the + * current maximum, save the current product.*/ for(i = 999; i >= 100; i--) { for(j = i; j >= 100; j--) { num = i * j; + /* Use the function defined in projecteuler.c to check if a number is palindrome.*/ if(num > max && is_palindrome(num, 10)) { max = num; diff --git a/C/p005.c b/C/p005.c index 91a3c8e..6d3c63d 100644 --- a/C/p005.c +++ b/C/p005.c @@ -1,3 +1,7 @@ +/* 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. + * + * What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?*/ + #include #include #include @@ -11,6 +15,7 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &start); + /* Function define in projecteuler.c to find the least common multiple of multiple numbers.*/ res = lcmm(n, 20); clock_gettime(CLOCK_MONOTONIC, &end); diff --git a/C/projecteuler.c b/C/projecteuler.c index e43f175..50beb6c 100644 --- a/C/projecteuler.c +++ b/C/projecteuler.c @@ -7,20 +7,29 @@ int partition(void **array, int l, int r, int (*cmp)(void *lv, void *rv)); int is_prime(long int num) { - int i, limit; + long int i, limit; if(num <= 3) { + /* If num is 2 or 3 then it's prime.*/ return num == 2 || num == 3; } + /* If num is divisible by 2 or 3 then it's not prime.*/ if(num % 2 == 0 || num % 3 == 0) { return 0; } + /* Any number can have only one prime factor greater than its + * square root. If we reach the square root and we haven't found + * any smaller prime factors, then the number is prime.*/ limit = floor(sqrt(num)); + /* Every prime other than 2 and 3 is in the form 6k+1 or 6k-1. + * If I check all those value no prime factors of the number + * will be missed. If a factor is found, the number is not prime + * and the function returns 0.*/ for(i = 5; i <= limit; i += 6) { if(num % i == 0 || num % (i + 2) == 0) @@ -29,11 +38,42 @@ int is_prime(long int num) } } + /* If no factor is found up to the square root of num, num is prime.*/ return 1; } +int is_palindrome(int num, int base) +{ + int reverse = 0, tmp; + + tmp = num; + + /* Start with reverse=0, get the rightmost digit of the number using + * modulo operation (num modulo base), add it to reverse. Remove the + * rightmost digit dividing num by the base, shift the reverse left + * multiplying by the base, repeat until all digits have been inserted + * in reverse order.*/ + while(tmp > 0) + { + reverse *= base; + reverse += tmp % base; + tmp /= base; + } + + /* If the reversed number is equal to the original one, then it's palindrome.*/ + if(num == reverse) + { + return 1; + } + + return 0; +} + long int gcd(long int a, long int b) { + /* Euclid's algorithm for the greatest common divisor: + * gcd(a, 0) = a + * gcd(a, b) = gcd(b, a modulo b)*/ if(b == 0) { return a; @@ -42,16 +82,19 @@ long int gcd(long int a, long int b) return gcd(b, a%b); } +/* Least common multiple algorithm using the greatest common divisor.*/ long int lcm(long int a, long int b) { return a * b / gcd(a, b); } +/* Recursive function to calculate the least common multiple of more than 2 numbers.*/ long int lcmm(long int *values, int n) { int i; long int value; + /* If there are only two numbers, use the lcm function to calculate the lcm.*/ if(n == 2) { return lcm(values[0], values[1]); @@ -65,6 +108,7 @@ long int lcmm(long int *values, int n) values[i] = values[i+1]; } + /* Recursively calculate lcm(a, b, c, ..., n) = lcm(a, lcm(b, c, ..., n)).*/ return lcm(value, lcmm(values, n-1)); } } @@ -207,27 +251,6 @@ void quick_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv)) quick_sort(array, i+1, r, cmp); } -int is_palindrome(int num, int base) -{ - int reverse = 0, tmp; - - tmp = num; - - while(tmp > 0) - { - reverse *= base; - reverse += tmp % base; - tmp /= base; - } - - if(num == reverse) - { - return 1; - } - - return 0; -} - int is_pandigital(int value, int n) { int *digits; diff --git a/C/projecteuler.h b/C/projecteuler.h index 34c50be..dedc2c0 100644 --- a/C/projecteuler.h +++ b/C/projecteuler.h @@ -2,14 +2,14 @@ #define _PROJECTEULER_INCLUDED int is_prime(long int); -long int lcmm(long int *values, int n); -long int lcm(long int a, long int b); +int is_palindrome(int num, int base); long int gcd(long int a, long int b); +long int lcm(long int a, long int b); +long int lcmm(long int *values, int n); int *sieve(int n); int count_divisors(int n); 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)); -int is_palindrome(int num, int base); int is_pandigital(int value, int n); int is_pentagonal(long int n); diff --git a/Python/projecteuler.py b/Python/projecteuler.py index a433aaa..7c03b5e 100644 --- a/Python/projecteuler.py +++ b/Python/projecteuler.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -from math import sqrt, floor +from math import sqrt, floor, gcd from numpy import ndarray, zeros @@ -19,12 +19,6 @@ def is_prime(num): return True -def gcd(a, b): - if b == 0: - return a - - return gcd(b, a%b) - def lcm(a, b): return a * b // gcd(a, b)