I have this code written in C to find all possible Pythagorean triplets within a certain number range. The original algorithm I wrote, just nested for loops and if(pow(a, 2) + pow(b, 2) == pow(c, 2)), worked just fine. However, my new, more optimized algorithm, which only loops through a and b, setting c to sqrt(pow(a, 2) + pow(b, 2)) and checking if ceil(c) == c, immediately begins accepting all whole numbers the moment b hits 969.
Furthermore, when I ran the second algorithm with a smaller amount and checked the results, the amount of triplets output is exactly 0.969x the limit of b (the top loop).
This is an extremely weird and interesting phenomenon, and I am unsure what makes 969 such a special number.
My new algorithm:
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(void) {
unsigned int limit;
printf("Max value to bruteforce: ");
scanf("%d", &limit);
unsigned int triples[limit][3]; // `0.969 * limit` is exact
unsigned int i = 0;
printf("Bruteforcing...\n");
for(unsigned int b = 1; b < limit; b++) {
for(unsigned int a = 1; a <= b; a++) {
double c = sqrt(pow(a, 2) + pow(b, 2));
if(ceil(c) == c) {
triples[i][0] = a;
triples[i][1] = b;
triples[i][2] = c;
i++;
printf("found: %d, %d, %d\n", a, b, (int) c);
}
}
}
char out[i + 15];
sprintf(out, "%d\n", limit);
for(int i2 = 0; i2 < i; i2++) {
for(int j = 0; j < 3; j++) {
char ln[10];
sprintf(ln, "%d ", triples[i2][j]);
strcat(out, ln);
}
strcat(out, "\n");
}
FILE *f = fopen("cache.txt", "w");
fprintf(f, "%s", out);
fclose(f);
printf("Saved to cache.txt\n");
return 0;
}
My old algorithm (reproduced, may not be 100% accurate):
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(void) {
unsigned int limit;
printf("Max value to bruteforce: ");
scanf("%d", &limit);
unsigned int triples[limit][3]; // `0.969 * limit` is exact
unsigned int i = 0;
printf("Bruteforcing...\n");
for(unsigned int b = 1; b < limit; b++) {
for(unsigned int a = 1; a <= b; a++) {
for(unsigned int c = 1; c < limit; c++) {
if(pow(a, 2) + pow(b, 2) == pow(c, 2)) {
triples[i][0] = a;
triples[i][1] = b;
triples[i][2] = c;
i++;
printf("found: %d, %d, %d\n", a, b, (int) c);
}
}
}
}
char out[i + 15];
sprintf(out, "%d\n", limit);
for(int i2 = 0; i2 < i; i2++) {
for(int j = 0; j < 3; j++) {
char ln[10];
sprintf(ln, "%d ", triples[i2][j]);
strcat(out, ln);
}
strcat(out, "\n");
}
FILE *f = fopen("cache.txt", "w");
fprintf(f, "%s", out);
fclose(f);
printf("Saved to cache.txt\n");
return 0;
}
Nothing, actually. The posted code has undefined behavior caused by access out of bounds of
tripletsand the wrong format specifier forlimit.limitis used to bound the value of the bigger cathetus, but it's not enough as count of the number of triplets.We can write a more simple (IMHO) version of the brute force algorithm, without using any floating-point function from
<math.h>:Live: https://godbolt.org/z/hvTa9zKW4