Ackermann

A function that grows faster than you can imagine, computed exactly and checked step by step.

ackermann.js · output · proof · check · try it in the playground


The question

Adding is repeated counting. Multiplying is repeated adding. Raising to a power is repeated multiplying. Keep going — repeated powers, then repeated that — and numbers explode.

The Ackermann function A(X, Y) climbs this ladder: X says which rung, Y how far to go. A(3, 4) is 125. A(4, 2) has 19,729 digits.

Can a computer get such numbers exactly right — and show how?


The ladder of operations

Mathematicians call the rungs hyperoperations. With base 2:

Level Operation Example
0 successor (add one) 7 + 1
1 addition 7 + 2
2 multiplication 7 × 2
3 exponentiation (power) 2⁷ = 128
4 tetration (tower of powers) 2^2^2^2 = 65,536

Each level above 3 is the level below, repeated. A(X, Y) shifts Y up by 3, applies level X with base 2, and subtracts 3 again.


What we tell eyecode

// A(X, Y): shift Y by 3, apply level X with base 2, and subtract 3 again.
implied_by(ackermann([X, Y], A), [is(B, add(Y, 3)), hyper(X, B, 2, C), is(A, sub(C, 3))])

// hyper(Level, Count, Base, Result)
implied_by(hyper(0, Y, _, A), is(A, add(Y, 1)))
implied_by(hyper(1, Y, Z, A), is(A, add(Y, Z)))
implied_by(hyper(2, Y, Z, A), is(A, mul(Y, Z)))
implied_by(hyper(3, Y, Z, A), is(A, pow(Z, Y)))
// Applied zero times, every level above 3 gives 1.
implied_by(hyper(X, 0, _, 1), gt(X, 3))
implied_by(
  hyper(X, Y, Z, A),
  [gt(X, 3), gt(Y, 0), is(B, sub(Y, 1)), hyper(X, B, Z, C), is(D, sub(X, 1)), hyper(D, C, Z, A)],
)

query(ackermann([3, 4], _))
// … ten more questions like this

The first four levels are plain arithmetic (is means “compute”; add, mul and pow are addition, multiplication and power, and gt is “greater than”). The last rule says: level X, Y times, is level X−1 applied to level X, Y−1 times. Everything is a backward rule, worked out only when a question asks for it.


What eyecode concludes

ackermann([0, 6], 7)
ackermann([2, 9], 21)
ackermann([3, 4], 125)
ackermann([3, 14], 131069)
ackermann([4, 1], 65533)
ackermann([4, 2], 2003529930406846464979072351560255750447825475569751419265016973710894…)
ackermann([5, 0], 65533)

7 of the 11 answers. The [4, 2] line goes on for 19,729 digits, ending in …5587895905719156733. eyecode’s integers have no size limit, so nothing is rounded.


Why: the proof in plain words

For A(3, 4) the proof says:

  1. 4 + 3 = 7 — a built-in calculation.
  2. 2⁷ = 128, so level 3 of 7 is 128 — rule 5.
  3. 128 − 3 = 125 — a built-in calculation.
  4. So A(3, 4) = 125 — rule 1, with X = 3, Y = 4.

A(4, 1) needs the repeating rule, rule 7: level 4 applied zero times is 1 (rule 6), then each application raises 2 to the previous result: 2, 4, 16, and finally 2¹⁶ = 65,536. The tower up to 16 was already proved for A(4, 0) = 13 and is reused: steps proved for one answer serve the next.


Checked, not just claimed

The checker read all 74 steps against the program:

Verdict: checked. Nothing taken on trust.


Try it

eyecode examples/ackermann.js            # the answers
eyecode --proof examples/ackermann.js    # answers with their proof

Or open it in the playground.

Add query(ackermann([3, 5], _)) at the end and run again: a new answer appears, ackermann([3, 5], 253).


Takeaway

Enormous numbers are no excuse for “trust me”. Every rung of the ladder is an ordinary rule, every sum and power is recomputed by an independent checker, and the answer is exact down to the last of its 19,729 digits.