For non-negative integers one can use Church numbers. The nice inc
function is due to @Oberon. The code isn't much readable by intention (the question is tagged code-trolling).
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define SIX '6' - '0'
#define NINE '9' - 50
typedef union p_ {
int i;
struct {
union p_* (*f)(union p_*, union p_*);
union p_* ctx1;
union p_* ctx2;
};
} p;
#define POOL_SIZE 140 // beware!
p pool[POOL_SIZE];
int usage = 0;
int inc(int i) {
return i&1 ? inc(i >> 1) << 1 : i | 1;
}
int post_inc(int* x) {
int res = *x;
*x = inc(*x);
return res;
}
p* p_from_i(int i) {
assert(usage < POOL_SIZE);
pool[usage].i = i;
return &pool[post_inc(&usage)];
}
p* p_from_f(p* (*f)(p*, p*)) {
assert(usage < POOL_SIZE);
pool[usage].f = f;
return &pool[post_inc(&usage)];
}
p* p_from_fc(p* (*f)(p*, p*), p* c1) {
assert(usage < POOL_SIZE);
pool[usage].f = f;
pool[usage].ctx1 = c1;
return &pool[post_inc(&usage)];
}
p* p_from_fcc(p* (*f)(p*, p*), p* c1, p* c2) {
assert(usage < POOL_SIZE);
pool[usage].f = f;
pool[usage].ctx1 = c1;
pool[usage].ctx2 = c2;
return &pool[post_inc(&usage)];
}
p* inc_p(p* self, p* i) {
return p_from_i(inc(i->i));
}
int to_int(p* n) {
p* zero = p_from_i(0);
p* inc = p_from_f(inc_p);
p* tmp = (n->f)(n, inc);
return tmp->f(tmp, zero)->i;
}
p* f1(p* self, p* n) {
return n;
}
p* f0(p* self, p* n) {
return p_from_f(f1);
}
p* h2(p* self, p* x) {
p* tmp1 = self->ctx1->f(self->ctx1, self->ctx2);
p* tmp2 = tmp1->f(tmp1, x);
return self->ctx2->f(self->ctx2, tmp2);
}
p* h1(p* self, p* f) {
return p_from_fcc(h2, self->ctx1, f);
}
p* h0(p* self, p* n) {
return p_from_fc(h1, n);
}
p* to_num_acc(int k, int i) {
p* zero = p_from_f(f0);
p* succ = p_from_f(h0);
if (i == k) {
return zero;
} else {
return succ->f(succ, to_num_acc(k, inc(i)));
}
}
p* to_num(int k) {
return to_num_acc(k, 0);
}
p* m2(p* self, p* f) {
return self->ctx1->f(self->ctx1, self->ctx2->f(self->ctx2, f));
}
p* m1(p* self, p* n) {
return p_from_fcc(m2, self->ctx1, n);
}
p* m0(p* self, p* m) {
return p_from_fc(m1, m);
}
p* times(p* x, p* y) {
p* mult = p_from_f(m0);
p* tmp1 = mult->f(mult, x);
p* tmp2 = tmp1->f(tmp1, y);
return tmp2;
}
int main() {
p* six = to_num(SIX);
p* nine = to_num(NINE);
printf("%d\n", to_int(times(six, nine)));
return 0;
}
Code is also available at pastebin.