Achtung: Bei Parametern jenseits von (4, 1) bzw. (3.13) geht das Ding natuerlich baden, weil die Zahlen einfach zu gross werden, und auf libgmp hatte ich keine Lust.
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Nicht wirklich das Original, sondern die Variante von Peter, die
* aber ebenfalls nicht primitiv-rekursiv ist:
*/
unsigned long ack_rec(unsigned long n, unsigned long m) {
if (!n)
return m + 1;
else if (!m)
return ack_rec(n - 1, 1);
else
return ack_rec(n - 1, ack_rec(n, m - 1));
}
/* Teil-iterativ: */
unsigned long ack_part_iter(unsigned long n, unsigned long m) {
for (; n; n--)
if (!m)
m = 1;
else
m = ack_part_iter(n, m - 1);
return m + 1;
}
/* Iterativ unter Verwendung eines expliziten Stacks: */
static void push(unsigned long);
static unsigned long pop(void); /* 0, wenn der Stack leer ist, weil wir niemals eine 0 pushen. */
unsigned long ack_iter_stack(unsigned long n, unsigned long m) {
start:
for (; n; n--)
if (m) {
m--;
push(n);
goto start;
} else
m = 1;
if (n = pop()) {
m++;
n--;
goto start;
}
return m + 1;
}
int main(int argc, char *argv[]) {
unsigned long n, m;
unsigned long (*ack)(unsigned long, unsigned long);
if (argc != 4 ||
!strchr("rpi", argv[1][0]) ||
argv[1][1] ||
sscanf(argv[2], "%lu", &n) != 1 ||
sscanf(argv[3], "%lu", &m) != 1) {
fputs("usage: plemplem [r | p | i] n m\n"
"\tr: recursive, p: partial iterative, "
"i: iterative, using a stack\n", stderr);
exit(1);
}
switch (argv[1][0]) {
case 'r':
ack = ack_rec;
break;
case 'p':
ack = ack_part_iter;
break;
case 'i':
ack = ack_iter_stack;
break;
}
printf("%lu\n", ack(n, m));
return 0;
}
/* Hier kommt nur noch das Stack-Geraffel */
static struct {
unsigned long *st_data;
unsigned long st_max;
unsigned long st_tos;
} st = { NULL, 0, 0 };
static void push(unsigned long n) {
if (st.st_tos >= st.st_max) {
st.st_max = st.st_max ? 2 * st.st_max : 1024;
if (!(st.st_data = realloc(st.st_data, st.st_max * sizeof(*(st.st_data)))))
err(1, NULL);
}
st.st_data[st.st_tos++] = n;
}
static unsigned long pop(void) {
return !st.st_tos ? 0 : st.st_data[--st.st_tos];
}