diff --git a/c_impl/.gitignore b/c_impl/.gitignore index 968b587..791e97b 100644 --- a/c_impl/.gitignore +++ b/c_impl/.gitignore @@ -1,2 +1,4 @@ src/*.o ReciprocalOfPalindromes +.cache +compile_commands.json diff --git a/c_impl/Makefile b/c_impl/Makefile index c4d8169..8ab4d04 100644 --- a/c_impl/Makefile +++ b/c_impl/Makefile @@ -1,9 +1,15 @@ +ifdef DEBUG + EXTRA_CFLAGS = -g -O0 +else + EXTRA_CFLAGS = -DNDEBUG -O3 +endif + CC ?= gcc -CFLAGS ?= -Wall -Wextra -Wpedantic +CFLAGS ?= -Wall -Wextra -Wpedantic ${EXTRA_CFLAGS} all: ReciprocalOfPalindromes -ReciprocalOfPalindromes: src/main.o +ReciprocalOfPalindromes: src/main.o src/palindrome_generator.o $(CC) $(CFLAGS) -o ReciprocalOfPalindromes $^ .PHONY: clean diff --git a/c_impl/src/main.c b/c_impl/src/main.c index 33c14ce..3cc4e66 100644 --- a/c_impl/src/main.c +++ b/c_impl/src/main.c @@ -1,3 +1,45 @@ -int main() { +#include +#include + +#include "palindrome_generator.h" + +#define LIMIT 128 + +// expects a const char* for "msg" +#define LOG(msg) do { \ + printf("%s:%u %s\n", __FILE__, __LINE__, msg); \ + } while (0); + +int main(int argc, char **argv) { + unsigned long long limit = LIMIT; + + if (argc == 1) { + // do nothing + } else if (argc == 2) { + limit = strtoull(argv[1], NULL, 10); + if (limit == 0) { + LOG("ERROR: Failed to parse arg into unsigned long long"); + return 1; + } + } else { + LOG("ERROR: Program requires one integer as its only argument, or no " + "args"); + return 2; + } + + printf("Generating sum of reciprocals of palindromes with \"limit\" of " + "%llu\n", + limit); + + double sum = 0.0; + PGeneratorState state = PGenerator_Init(); + + while(limit > 0) { + --limit; + sum += 1.0 / (double)(PGenerator_Next(&state)); + } + + printf("Resulting sum == %lf, last state is %llu\n", sum, state.current); + return 0; } diff --git a/c_impl/src/palindrome_generator.c b/c_impl/src/palindrome_generator.c new file mode 100644 index 0000000..6c5f606 --- /dev/null +++ b/c_impl/src/palindrome_generator.c @@ -0,0 +1,64 @@ +#include "palindrome_generator.h" + +PGeneratorState PGenerator_Init() { + return (PGeneratorState){0}; +} + +// TODO needs testing +int PGeneratorInternal_IsPalindrome(unsigned long long n) { + unsigned int digits = 0; + + for (unsigned long long i = n; i > 0; i /= 10) { + ++digits; + } + + if (digits == 0) { + // invalid state + return 1; + } + + // end as in "least signifciant digit end" + unsigned int end = 0; + // start as in "most significant digit start" + unsigned int start = digits - 1; + unsigned long long temp, temp2, temp3; + while (end < start) { + // get end value + temp = n; + temp2 = 0; + while (temp2 < end) { + ++temp2; + temp /= 10; + } + temp %= 10; + + // get start value + temp2 = n; + temp3 = 0; + while (temp3 < start) { + ++temp3; + temp2 /= 10; + } + temp2 %= 10; + + // compare + if (temp != temp2) { + // mismatch, we now know it's not a palindrome + return 0; + } else { + // matches, cannot yet prove it is a palindrome until convergence + ++end; + --start; + } + } + + // no mismatches, at this point it has to be a palindrome + return 1; +} + +unsigned long long PGenerator_Next(PGeneratorState *state) { + do { + ++state->current; + } while(!PGeneratorInternal_IsPalindrome(state->current)); + return state->current; +} diff --git a/c_impl/src/palindrome_generator.h b/c_impl/src/palindrome_generator.h new file mode 100644 index 0000000..e9e372c --- /dev/null +++ b/c_impl/src/palindrome_generator.h @@ -0,0 +1,11 @@ +#ifndef SUM_OF_RECIPROCALS_OF_PALINDROMES_PALINDROME_GENERATOR_H_ +#define SUM_OF_RECIPROCALS_OF_PALINDROMES_PALINDROME_GENERATOR_H_ + +typedef struct PGeneratorState { + unsigned long long current; +} PGeneratorState; + +PGeneratorState PGenerator_Init(); +unsigned long long PGenerator_Next(PGeneratorState *state); + +#endif