Jordan-Pólya numbers: Difference between revisions

Content added Content deleted
m (→‎{{header|Julia}}: revise aupto per phix, etc code)
(Added C)
Line 24: Line 24:


__TOC__
__TOC__

=={{header|C}}==
{{trans|Wren}}
{{libheader|GLib}}
A translation of the second version. Run time less than 0.5 seconds.
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <locale.h>
#include <glib.h>

uint64_t factorials[19] = {1, 1};

void cacheFactorials() {
uint64_t fact = 1;
int i;
for (i = 2; i < 19; ++i) {
fact *= i;
factorials[i] = fact;
}
}

int findNearestFact(uint64_t n) {
int i;
for (i = 1; i < 19; ++i) {
if (factorials[i] >= n) return i;
}
return 18;
}

int findNearestInArray(GArray *a, uint64_t n) {
int i;
for (i = 0; i < a->len; ++i) {
if (g_array_index(a, uint64_t, i) >= n) return i;
}
return a->len;
}

GArray *jordanPolya(uint64_t limit) {
int i, ix, k, l, p;
uint64_t t, rk, kl;
GArray *res = g_array_new(false, false, sizeof(uint64_t));
ix = findNearestFact(limit);
for (i = 0; i <= ix; ++i) {
t = factorials[i];
g_array_append_val(res, t);
}
k = 2;
while (k < res->len) {
rk = g_array_index(res, uint64_t, k);
for (l = 2; l < res->len; ++l) {
t = g_array_index(res, uint64_t, l);
if (t > limit/rk) break;
kl = t * rk;
while (true) {
p = findNearestInArray(res, kl);
if (p < res->len && g_array_index(res, uint64_t, p) != kl) {
g_array_insert_val(res, p, kl);
} else if (p == res->len) {
g_array_append_val(res, kl);
}
if (kl > limit/rk) break;
kl *= rk;
}
}
++k;
}
return g_array_remove_index(res, 0);
}

GArray *decompose(uint64_t n, int start) {
uint64_t i, s, t, m, prod;
GArray *f, *g;
for (s = start; s > 0; --s) {
f = g_array_new(false, false, sizeof(uint64_t));
if (s < 2) return f;
m = n;
while (!(m % factorials[s])) {
g_array_append_val(f, s);
m /= factorials[s];
if (m == 1) return f;
}
if (f->len > 0) {
g = decompose(m, s - 1);
if (g->len > 0) {
prod = 1;
for (i = 0; i < g->len; ++i) {
prod *= factorials[(int)g_array_index(g, uint64_t, i)];
}
if (prod == m) {
for (i = 0; i < g->len; ++i) {
t = g_array_index(g, uint64_t, i);
g_array_append_val(f, t);
}
g_array_free(g, true);
return f;
}
}
g_array_free(g, true);
}
g_array_free(f, true);
}
}

char *superscript(int n) {
char* ss[] = {"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"};
if (n < 10) return ss[n];
static char buf[7];
sprintf(buf, "%s%s", ss[n/10], ss[n%10]);
return buf;
}
int main() {
int i, j, ix, count;
uint64_t t, u;
GArray *v, *w;
cacheFactorials();
v = jordanPolya(1ull << 53);
printf("First 50 Jordan-Pólya numbers:\n");
for (i = 0; i < 50; ++i) {
printf("%4ju ", g_array_index(v, uint64_t, i));
if (!((i + 1) % 10)) printf("\n");
}
printf("\nThe largest Jordan-Pólya number before 100 millon: ");
setlocale(LC_NUMERIC, "");
ix = findNearestInArray(v, 100000000ull);
printf("%'ju\n\n", g_array_index(v, uint64_t, ix - 1));

uint64_t targets[5] = {800, 1050, 1800, 2800, 3800};
for (i = 0; i < 5; ++i) {
t = g_array_index(v, uint64_t, targets[i] - 1);
printf("The %'juth Jordan-Pólya number is : %'ju\n", targets[i], t);
w = decompose(t, 18);
count = 1;
t = g_array_index(w, uint64_t, 0);
printf(" = ");
for (j = 1; j < w->len; ++j) {
u = g_array_index(w, uint64_t, j);
if (u != t) {
if (count == 1) {
printf("%ju! x ", t);
} else {
printf("(%ju!)%s x ", t, superscript(count));
count = 1;
}
t = u;
} else {
++count;
}
}
if (count == 1) {
printf("%ju! x ", t);
} else {
printf("(%ju!)%s x ", t, superscript(count));
}
printf("\b\b \n\n");
g_array_free(w, true);
}
g_array_free(v, true);
return 0;
}</syntaxhighlight>

{{out}}
<pre>
First 50 Jordan-Pólya numbers:
1 2 4 6 8 12 16 24 32 36
48 64 72 96 120 128 144 192 216 240
256 288 384 432 480 512 576 720 768 864
960 1024 1152 1296 1440 1536 1728 1920 2048 2304
2592 2880 3072 3456 3840 4096 4320 4608 5040 5184

The largest Jordan-Pólya number before 100 millon: 99,532,800

The 800th Jordan-Pólya number is : 18,345,885,696
= (4!)⁷ x (2!)²

The 1,050th Jordan-Pólya number is : 139,345,920,000
= 8! x (5!)³ x 2!

The 1,800th Jordan-Pólya number is : 9,784,472,371,200
= (6!)² x (4!)² x (2!)¹⁵

The 2,800th Jordan-Pólya number is : 439,378,587,648,000
= 14! x 7!

The 3,800th Jordan-Pólya number is : 7,213,895,789,838,336
= (4!)⁸ x (2!)¹⁶
</pre>


=={{header|J}}==
=={{header|J}}==