From 3b3a5633194f1a36f655833065632f5ec36fef68 Mon Sep 17 00:00:00 2001 From: Daniele Fucini Date: Thu, 3 Oct 2019 15:17:27 +0200 Subject: [PATCH] Add solution for problem 104 in C --- C/p104.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 C/p104.c diff --git a/C/p104.c b/C/p104.c new file mode 100644 index 0000000..20f3fe6 --- /dev/null +++ b/C/p104.c @@ -0,0 +1,117 @@ +/* The Fibonacci sequence is defined by the recurrence relation: +* +* F_n = F_n−1 + F_n−2, where F_1 = 1 and F_2 = 1. +* It turns out that F_541, which contains 113 digits, is the first Fibonacci number for which the last nine digits are 1-9 pandigital +* (contain all the digits 1 to 9, but not necessarily in order). And F_2749, which contains 575 digits, is the first Fibonacci number +* for which the first nine digits are 1-9 pandigital. +* +* Given that F_k is the first Fibonacci number for which the first nine digits AND the last nine digits are 1-9 pandigital, find k.*/ + +#include +#include +#include +#include +#include "projecteuler.h" + +void fib_calc(mpz_t fib, int n); + +int main(int argc, char **argv) +{ + unsigned int i = 2, j, fib1 = 1, fib2 = 1, fibn, fib_int, found = 0; + char *fib_str; + double elapsed; + struct timespec start, end; + mpz_t fib; + + clock_gettime(CLOCK_MONOTONIC, &start); + + mpz_init(fib); + + while(!found) + { + /* Calculate the next Fibonacci number modulo 10^9 and check if the result is 1-9 pandigital.*/ + fibn = (fib1 + fib2) % 1000000000; + fib1 = fib2; + fib2 = fibn; + i++; + + /* If the last 9 digits of fib_n are pandigital, calculate the ith Fibonacci number using + * the matrix representation.*/ + if(is_pandigital(fibn, 9)) + { + fib_calc(fib, i); + fib_str = mpz_get_str(NULL, 10, fib); + + fib_int = 0; + + for(j = 0; j < 9; j++) + { + fib_int *= 10; + fib_int += fib_str[j] - '0'; + } + + if(is_pandigital(fib_int, 9)) + { + found = 1; + } + + free(fib_str); + } + } + + mpz_clear(fib); + + clock_gettime(CLOCK_MONOTONIC, &end); + + elapsed = (end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1000000000; + + printf("Project Euler, Problem 104\n"); + printf("Answer: %d\n", i); + + printf("Elapsed time: %.9lf seconds\n", elapsed); + + return 0; +} + +void fib_calc(mpz_t fib, int n) +{ + int i; + mpz_t tmp, tmp00, tmp01, tmp10, tmp11; + mpz_t fib_matrix_base[2][2], fib_matrix[2][2]; + + mpz_init_set_ui(fib_matrix_base[0][0], 1); + mpz_init_set_ui(fib_matrix_base[0][1], 1); + mpz_init_set_ui(fib_matrix_base[1][0], 1); + mpz_init_set_ui(fib_matrix_base[1][1], 0); + mpz_init_set_ui(fib_matrix[0][0], 1); + mpz_init_set_ui(fib_matrix[0][1], 1); + mpz_init_set_ui(fib_matrix[1][0], 1); + mpz_init_set_ui(fib_matrix[1][1], 0); + mpz_inits(tmp, tmp00, tmp01, tmp10, tmp11, NULL); + + for(i = 0; i < n - 1; i++) + { + mpz_mul(tmp00, fib_matrix[0][0], fib_matrix_base[0][0]); + mpz_mul(tmp, fib_matrix[0][1], fib_matrix_base[1][0]); + mpz_add(tmp00, tmp00, tmp); + mpz_mul(tmp01, fib_matrix[0][0], fib_matrix_base[0][1]); + mpz_mul(tmp, fib_matrix[0][1], fib_matrix_base[1][1]); + mpz_add(tmp01, tmp01, tmp); + mpz_mul(tmp10, fib_matrix[1][0], fib_matrix_base[0][0]); + mpz_mul(tmp, fib_matrix[1][1], fib_matrix_base[1][0]); + mpz_add(tmp10, tmp10, tmp); + mpz_mul(tmp11, fib_matrix[1][0], fib_matrix_base[0][1]); + mpz_mul(tmp, fib_matrix[1][1], fib_matrix_base[1][1]); + mpz_add(tmp11, tmp11, tmp); + mpz_set(fib_matrix[0][0], tmp00); + mpz_set(fib_matrix[0][1], tmp01); + mpz_set(fib_matrix[1][0], tmp10); + mpz_set(fib_matrix[1][1], tmp11); + } + + mpz_set(fib, fib_matrix[0][1]); + + mpz_clears(tmp, tmp00, tmp01, tmp10, tmp11, fib_matrix_base[0][0], + fib_matrix_base[0][1], fib_matrix_base[1][0], fib_matrix_base[1][1], + fib_matrix[0][0], fib_matrix[1][0], fib_matrix[1][1], NULL); +} diff --git a/README.md b/README.md index 8888e98..618f294 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,4 @@ These are my solutions in C and Python, not necessarily the best solutions. I've solved most of the first 100 problems, currently working on cleaning the code and uploading it. I will try to solve more problems in the future. # Important -Using these solutions to solve Project Euler problems that you haven't solved yet is highly discouraged. What's the point of cheating, anyway? +Using these solutions to solve Project Euler problems that you haven't solved yet is highly discouraged. What's the point of cheating, anyway? There's nothing to win and it just spoils all the fun.