diff --git a/C/p016.c b/C/p016.c index 9c3558e..9940ae4 100644 --- a/C/p016.c +++ b/C/p016.c @@ -1,3 +1,7 @@ +/* 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. + * + * What is the sum of the digits of the number 2^1000?*/ + #include #include #include @@ -11,6 +15,8 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &start); + /* Simply calculate 2^1000 with the GMP Library + * and sum all the digits.*/ mpz_init_set_ui(p, 2); mpz_init_set_ui(sum, 0); mpz_init(r); @@ -19,6 +25,7 @@ int main(int argc, char **argv) while(mpz_cmp_ui(p, 0)) { + /* To get each digit, simply get the reminder of the division by 10.*/ mpz_tdiv_qr_ui(p, r, p, 10); mpz_add(sum, sum, r); } diff --git a/C/p017.c b/C/p017.c index c5c2d44..f183687 100644 --- a/C/p017.c +++ b/C/p017.c @@ -1,12 +1,24 @@ +/* If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total. + * + * If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used? + * + * NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) + * contains 20 letters. The use of "and" when writing out numbers is in compliance with British usage.*/ + #include #include #include int main(int argc, char **argv) { + /* Number of letters for numbers from 1 to 19.*/ int n1_19[19] = {3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8}; + /* Number of letters for "twenty", "thirty", ..., "ninety".*/ int n20_90[8] = {6, 6, 5, 5, 5, 7, 6, 6}; + /* Number of letters for "one hundred and", "two hundred and", ..., + * "nine hundred and".*/ int n100_900[9] = {13, 13, 15, 14, 14, 13, 15, 15, 14}; + /* Number of letters for 1000.*/ int n1000 = 11; int sum = 0, i, j; double elapsed; @@ -14,14 +26,19 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &start); + /* Sum the letters of the first 19 numbers.*/ for(i = 0; i < 19; i++) { sum += n1_19[i]; } + /* Add the letters of the numbers from 20 to 99.*/ for(i = 0; i < 8; i++) { + /* "Twenty", "thirty", ... "ninety" are used ten times each + * (e.g. "twenty", "twenty one", "twenty two", ..., "twenty nine").*/ n20_90[i] *= 10; + /* Add "one", "two", ..., "nine".*/ for(j = 0; j < 9; j++) { n20_90[i] += n1_19[j]; @@ -29,20 +46,27 @@ int main(int argc, char **argv) sum += n20_90[i]; } + /* Add the letters of the numbers from 100 to 999.*/ for(i = 0; i < 9; i++) { + /* "One hundred and", "two hundred and",... are used 100 times each.*/ n100_900[i] *= 100; + /* Add "one" to "nineteen".*/ for(j = 0; j < 19; j++) { n100_900[i] += n1_19[j]; } + /* Add "twenty" to "ninety nine", previously calculated.*/ for(j = 0; j < 8; j++) { n100_900[i] += n20_90[j]; } + /* "One hundred", "two hundred", ... don't have the "and", so remove + * three letters for each of them.*/ sum += n100_900[i] - 3; } + /* Add "one thousand".*/ sum += n1000; clock_gettime(CLOCK_MONOTONIC, &end); diff --git a/C/p019.c b/C/p019.c index 20c9987..58de517 100644 --- a/C/p019.c +++ b/C/p019.c @@ -1,3 +1,16 @@ +/* You are given the following information, but you may prefer to do some research for yourself. + * + * 1 Jan 1900 was a Monday. + * Thirty days has September, + * April, June and November. + * All the rest have thirty-one, + * Saving February alone, + * Which has twenty-eight, rain or shine. + * And on leap years, twenty-nine. + * A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400. + * + * How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?*/ + #include #include #include @@ -21,6 +34,9 @@ int main(int argc, char **argv) while(year < 2001) { + /* February has 29 days on leap years, otherwise 28. Leap years are those + * divisible by 4, but not if they're divisible by 100, except when they're + * divisible by 400.*/ if(month == feb) { if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) @@ -32,24 +48,33 @@ int main(int argc, char **argv) limit = 28; } } + /* April, June, September and November have 30 days.*/ else if(month == apr || month == jun || month == sep || month == nov) { limit = 30; } + /* All other months have 31 days.*/ else { limit = 31; } + /* Loop on every day of the month.*/ for(i = 1; i <= limit; i++) { + /* If it's the first day of the month and it's Sunday, increase + * counter, except if year=1900 (we need to count Sundays from + * 1901 to 2000.*/ if(year > 1900 && i == 1 && day == sun) { count++; } + /* Change day of the week.*/ day = (day + 1) % 7; } + /* At the end of the month, go to next month.*/ month = (month + 1) % 12; + /* If we're back to january, increase the year.*/ if(month == jan) { year++; diff --git a/C/p020.c b/C/p020.c index bab75c2..3524a23 100644 --- a/C/p020.c +++ b/C/p020.c @@ -1,3 +1,10 @@ +/* n! means n × (n − 1) × ... × 3 × 2 × 1 + * + * For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, + * and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27. + * + * Find the sum of the digits in the number 100!*/ + #include #include #include @@ -11,6 +18,7 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &start); + /* Calculate the factorial using the GMP Library and sum the digits.*/ mpz_inits(fact, r, sum, NULL); mpz_fac_ui(fact, 100); diff --git a/C/p021.c b/C/p021.c index b4c4b31..1f142be 100644 --- a/C/p021.c +++ b/C/p021.c @@ -1,9 +1,16 @@ +/* Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). + * If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers. + * + * For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. + * The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220. + +Evaluate the sum of all the amicable numbers under 10000.*/ + #include #include #include #include - -int sum_of_d(int n); +#include "projecteuler.h" int main(int argc, char **argv) { @@ -15,8 +22,12 @@ int main(int argc, char **argv) for(i = 2; i < 10000; i++) { - n = sum_of_d(i); - if(i != n && sum_of_d(n) == i) + /* Calculate the sum of proper divisors with the function + * implemented in projecteuler.c.*/ + n = sum_of_divisors(i); + /* 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) { sum += i + n; } @@ -35,24 +46,3 @@ int main(int argc, char **argv) return 0; } - -int sum_of_d(int n) -{ - int i, sum = 1, limit; - - limit = floor(sqrt(n)); - - for(i = 2; i <= limit; i++) - { - if(n % i == 0) - { - sum += i; - if(n != i * i) - { - sum += (n / i); - } - } - } - - return sum; -} diff --git a/C/p022.c b/C/p022.c index 3f4b35b..e963be2 100644 --- a/C/p022.c +++ b/C/p022.c @@ -1,3 +1,11 @@ +/* Using names.txt, a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. + * Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score. + * + * For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. + * So, COLIN would obtain a score of 938 × 53 = 49714. + * + * What is the total of all the name scores in the file?*/ + #include #include #include @@ -29,6 +37,7 @@ int main(int argc, char **argv) len = strlen(line); n = 1; + /* Count the names in the file.*/ for(i = 0; i < len; i++) { if(line[i] == ',') @@ -43,6 +52,7 @@ int main(int argc, char **argv) return 1; } + /* Save each name in a string.*/ names[0] = strtok(line, ",\""); for(i = 1; i < n; i++) @@ -50,8 +60,10 @@ int main(int argc, char **argv) names[i] = strtok(NULL, ",\""); } + /* Use quick_sort algorithm implemented in projecteuler.c to sort the names.*/ quick_sort((void **)names, 0, n-1, compare); + /* Calculate the score of each name an multiply by its position.*/ for(i = 0; i < n; i++) { len = strlen(names[i]); @@ -77,6 +89,7 @@ int main(int argc, char **argv) return 0; } +/* Function to compare two strings, to pass to the quick_sort function.*/ int compare(void *string1, void *string2) { char *s1, *s2; diff --git a/C/p023.c b/C/p023.c index 28ffd8a..247e9fe 100644 --- a/C/p023.c +++ b/C/p023.c @@ -1,7 +1,20 @@ +/* A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. + * For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number. + * + * A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n. + * + * As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. + * By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. + * However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed + * as the sum of two abundant numbers is less than this limit. + * + * Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.*/ + #include #include #include #include +#include "projecteuler.h" int is_abundant(int n); @@ -16,20 +29,13 @@ int main(int argc, char **argv) for(i = 0; i < 28123; i++) { - if(i < 11) - { - ab_nums[i] = 0; - } - else if(is_abundant(i+1)) - { - ab_nums[i] = 1; - } - else - { - ab_nums[i] = 0; - } + /* Find all abundant numbers smaller than 28123.*/ + ab_nums[i] = is_abundant(i+1); } + /* For every abundant number, sum every other abundant number greater + * than itself, until the sum exceeds 28123. Record that the resulting + * number is the sum of two abundant numbers.*/ for(i = 0; i < 28123; i++) { if(ab_nums[i]) @@ -44,6 +50,10 @@ int main(int argc, char **argv) { sums[sum-1] = 1; } + else + { + break; + } } } } @@ -51,6 +61,7 @@ int main(int argc, char **argv) sum = 0; + /* Sum every number that was not found as a sum of two abundant numbers.*/ for(i = 0; i < 28123; i++) { if(!sums[i]) @@ -73,22 +84,5 @@ int main(int argc, char **argv) int is_abundant(int n) { - int i, sum = 1, limit; - - limit = floor(sqrt(n)); - - for(i = 2; i <= limit; i++) - { - if(n % i == 0) - { - sum += i; - - if(n != i*i) - { - sum += (n / i); - } - } - } - - return sum > n; + return sum_of_divisors(n) > n; }