p0042_s0.c
problem 42 · 63 lines
/* Solution to Euler Problem 42: Coded Triangle Numbers. */
#include "runner.h"
#include <math.h>
/* True iff n is triangular, tested via the inverse identity: 8n+1 is a perfect square. */
static int is_triangle_number(int n) {
double sq = sqrt((double)(8 * n + 1));
long long sq_int = (long long)round(sq);
/* Round-trip in 64-bit integers to confirm the root exactly, guarding against fp rounding. */
return (sq_int * sq_int == (long long)(8 * n + 1));
}
/* Word value: sum of 1-based alphabet positions (A=1..Z=26) of each letter. */
static int word_to_num(const char *word) {
int sum = 0;
for (const char *c = word; *c != '\0'; c++) {
if (*c >= 'A' && *c <= 'Z') {
sum += (*c - 'A' + 1);
} else if (*c >= 'a' && *c <= 'z') {
sum += (*c - 'a' + 1);
}
}
return sum;
}
/* Count words whose value is triangular via the 8n+1-perfect-square test; O(W*L) over W words. */
const char *solve(int argc, char *argv[]) {
static char _answer[32];
if (argc < 2) { snprintf(_answer, sizeof _answer, "%lld", (long long)(-1)); return _answer; }
const char *file_url = argv[1];
char *text = get_text_file(file_url);
if (!text) { snprintf(_answer, sizeof _answer, "%lld", (long long)(-1)); return _answer; }
long long count = 0;
char *saveptr = NULL;
char *token = strtok_r(text, ",", &saveptr);
while (token != NULL) {
char word[256];
int wi = 0;
for (int i = 0; token[i] != '\0' && wi < 255; i++) {
char ch = token[i];
if (ch == '"' || ch == '\r' || ch == '\n' || ch == ' ') continue;
word[wi++] = ch;
}
word[wi] = '\0';
if (wi > 0) {
int score = word_to_num(word);
if (is_triangle_number(score)) {
count++;
}
}
token = strtok_r(NULL, ",", &saveptr);
}
free(text);
{ snprintf(_answer, sizeof _answer, "%lld", (long long)(count)); return _answer; }
}