Siehe auch gaga.html.

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