Impl limited C solution to problem

This commit is contained in:
Stephen Seo 2022-01-08 19:52:45 +09:00
parent 91c0654dec
commit 7e3fc05cf1
5 changed files with 128 additions and 3 deletions

2
c_impl/.gitignore vendored
View file

@ -1,2 +1,4 @@
src/*.o
ReciprocalOfPalindromes
.cache
compile_commands.json

View file

@ -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

View file

@ -1,3 +1,45 @@
int main() {
#include <stdlib.h>
#include <stdio.h>
#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;
}

View file

@ -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;
}

View file

@ -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