The Ackermann function

36

2

The Ackermann function is notable for being the one of the simplest examples of a total, computable function that isn't primitive recursive.

We will use the definition of A(m,n) taking in two nonnegative integers where

A(0,n) = n+1
A(m,0) = A(m-1,1)
A(m,n) = A(m-1,A(m,n-1))

You may implement

  • a named or anonymous function taking two integers as input, returning an integer, or
  • a program taking two space- or newline-separated integers on STDIN, printing a result to STDOUT.

You may not use an Ackermann function or hyperexponentiation function from a library, if one exists, but you may use any other function from any other library. Regular exponentiation is allowed.

Your function must be able to find the value of A(m,n) for m ≤ 3 and n ≤ 10 in less than a minute. It must at least theoretically terminate on any other inputs: given infinite stack space, a native Bigint type, and an arbitrarily long period of time, it would return the answer. Edit: If your language has a default recursion depth that is too restrictive, you may reconfigure that at no character cost.

The submission with the shortest number of characters wins.

Here are some values, to check your answer:

  A  | n=0     1     2     3     4     5     6     7     8     9    10
-----+-----------------------------------------------------------------
 m=0 |   1     2     3     4     5     6     7     8     9    10    11
   1 |   2     3     4     5     6     7     8     9    10    11    12
   2 |   3     5     7     9    11    13    15    17    19    21    23
   3 |   5    13    29    61   125   253   509  1021  2045  4093  8189
   4 |  13 65533   big   really big...

algorithmshark

Posted 2014-10-22T04:38:29.693

Reputation: 8 144

15How has this not been asked before?? – Calvin's Hobbies – 2014-10-22T04:56:22.963

Tried in Python, got ~60 bytes and a lot of stack overflows. Decided not to post as anything that can only calculate m <= 2 is not very useful :D – PurkkaKoodari – 2014-10-22T06:37:49.247

9I think it'd be more fun to make this [tag:fastest-code] – Sp3000 – 2014-10-22T07:43:48.480

22Downvoting because there's no challenge here. The obvious answer -- just naively implementing the function exactly according to its definition -- is always going to be the best answer. So the question is just "Which language has the least number of characters in the obvious expression of Ackermann's function?" The true winner is the programming language, not the person who wrote the obvious program in it. – David Richerby – 2014-10-22T07:52:22.060

I agree that this challenge would be more interesting as a fastest code, currently this challenge seems to be mostly, how can I implement the ackerman function in as little characters without much consideration to speed. Instead of how can I make use of any patterns in the ackerman function to speed it up – Tally – 2014-10-22T08:55:05.000

1What if my language's recursion limit is too low to compute A(3,8) and above as naively as the others did? Do I have to come up with a non-recursion solution, or can I also just "assume infinite stack space" in these cases? I'm fairly certain, it would terminate within a minute. – Martin Ender – 2014-10-22T09:53:31.603

5@DavidRicherby "The obvious answer [...] is always going to be the best answer." This is not true of all languages. I feel a little dirty for only having an example in my home language, but there are multiple ways to express Ackermann and in some languages you can get savings by using that fact. This was my intention for the challenge. – algorithmshark – 2014-10-22T13:15:37.463

1

@Sp3000 A problem with fastest-code is what counts as cheating. My SO answer to a related question at http://stackoverflow.com/a/12188327/400547 used shortcuts for m < 3 and one could add return BigInteger.Pow(2, n + 3) - 3 for m == 3 too. Does that count as cheating?

– Jon Hanna – 2014-10-23T00:34:31.657

Answers

7

Pyth, 19

DaGHR?atG?aGtHH1GhH

Defines a, which works as the Ackermann function. Note that this requires a higher recursion depth than the official pyth compiler allowed up until today to compute a 3 10, so I increased the recursion depth. This is not a change to the language, just to the compiler.

Test:

$ time pyth -c "DaGHR?atG?aGtHH1GhH           ;a 3 10"
8189

real    0m0.092s
user    0m0.088s
sys     0m0.000s

Explanation:

DaGH                     def a(G,H):
    R                    return
    ?          G                (if G:
     atG                              (a(G-1,
        ?    H                               (if H:
         aGtH                                      a(G,H-1)
              1                               else:1)
                hH               else:H+1)

Essentially, it first conditions on the truth value of G whether to recurse or return H+1. If it is recursing, the first argument is always G-1, and it conditions on the truth value of H whether to use a(G,H-1) as the second argument, or to use 1 as the second argument.

isaacg

Posted 2014-10-22T04:38:29.693

Reputation: 39 268

In modern Pyth (I assume this was added after this challenge) I think you can more or less change DaGHR to M and a to g. (Did the order of arguments for ? change?) – Lynn – 2015-12-16T13:39:34.937

@Mauris Yes, you can use M instead, and yes, ? argument order changed. It's now condition, true, false. It was true, condition, false. – isaacg – 2015-12-16T23:25:13.647

@Lynn Fun Pyth history facts: This question actually influenced isaacg to change (at least) two things about Pyth: the recursion limit and the change to M!

– FryAmTheEggman – 2016-03-16T17:39:33.520

23

Haskell, 35

0%n=1+n
m%n=iterate((m-1)%)1!!(n+1)

this defines the operator function %.

this works by noticing that m%n (where a is the ackerman function) for nonzero m is (m-1)% applied n+1 times to 1. for example, 3%2 is defined as 2%(3%1) which is 2%(2%(3%0)), and this is 2%(2%(2%1))

proud haskeller

Posted 2014-10-22T04:38:29.693

Reputation: 5 866

What am I doing wrong? – Dennis – 2018-03-12T00:59:07.460

wow, this has been wrong for so long, and nobody, including myself, noticed? good work. so it seems I mistakenly copied the first version of the answer, which was faulty, maybe by mistake or because I thought it worked. – proud haskeller – 2018-03-21T07:22:57.147

too bad I can't use 0%n instead of n+1 because of precedence – proud haskeller – 2014-12-04T21:19:56.110

12

GolfScript (30)

{1$1>{1\){1$(\A}*\;}{+)}if}:A;

Online demo

Without the 1> (which special-cases A(1, n)) it takes 9 minutes to compute A(3, 10) on the computer I've tested it on. With that special case it's fast enough that the online demo takes less than 10 seconds.

Note that this isn't a naïve translation of the definition. The recursion depth is bounded by m.

Dissection

{             # Function boilerplate
  1$          # Get a copy of m: stack holds m n m
  1>{         # (Optimisation): if m is greater than 1
    1         #   Take this as the value of A(m, -1)
    \){       #   Repeat n+1 times:
              #     Stack: m A(m, i-1)
      1$(\    #     Stack: m m-1 A(m, i-1)
      A       #     Stack: m A(m, i)
    }*
    \;        #   Lose that unwanted copy of m
  }{          # Else
    +)        #   A(m in {0, 1}, n) = m + n + 1
  }if
}:A;          # Function boilerplate

Peter Taylor

Posted 2014-10-22T04:38:29.693

Reputation: 41 901

In CJam, you wouldn't need 1>. After removal (and changing if to ?), computing 3 10 A takes 110 seconds with the online interpreter and six seconds with the Java interpreter. – Dennis – 2014-10-22T14:03:46.997

8

Binary lambda calculus, 54 bits = 6.75 bytes

Hexdump:

00000000: 1607 2d88 072f 68                        ..-../h

Binary:

000101100000011100101101100010000000011100101111011010

This is λm. mg. λn. g (n g 1)) (λn. λf. λx. f (n f x)), where all numbers are represented as Church numerals.

Anders Kaseorg

Posted 2014-10-22T04:38:29.693

Reputation: 29 242

6

JavaScript, ES6, 41 34 bytes

f=(m,n)=>m?f(m-1,!n||f(m,n-1)):n+1

Run this in a latest Firefox Console and it will create a function called f which you can call with different values of m and n like

f(3,2) // returns 29

OR

try the code below in a latest Firefox

f=(m,n)=>m?f(m-1,!n||f(m,n-1)):n+1

B.onclick=_=>alert(f(+M.value, +N.value))
#M,#N{max-width:15px;border: 1px solid;border-width:0 0 1px 0}
<div>f(<input id=M />,<input id=N />)</div><br><button id=B>Evaluate</button>

Optimizer

Posted 2014-10-22T04:38:29.693

Reputation: 25 836

Wow... we have 4 practically identical JS solutions, all at 34 bytes. I've never seen that before. – ETHproductions – 2015-12-15T20:24:48.207

Testing this with 0,1 in Chrome gives no result. – Nzall – 2014-10-22T08:36:36.653

3Pl read, this only works in latest Firefox due to ES6 – Optimizer – 2014-10-22T08:42:00.383

6

Python 2.7.8 - 80, 54, 48, 46 45

A=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n

(Credits to xnor!)

More readable, but with 1 more character:

A=lambda m,n:n+(m<1or A(m-1,n<1or A(m,n-1))-n)

Not that I had to set sys.setrecursionlimit(10000) in order to get a result for A(3,10). Further golfing using logical indexing did not work due to the dramatically growing recursion depth.

Falko

Posted 2014-10-22T04:38:29.693

Reputation: 5 307

I get a syntax error on the 1else. The start letter e causes trouble for the parser because numbers can be written like 1e3. – xnor – 2014-10-22T08:09:52.787

Saved a few chars switching to and/or: A=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n – xnor – 2014-10-22T08:17:16.947

@xnor: Thanks for the tip! See this discussion for the parsing issue issue. Python 2.7.8 accepts 1else, most other versions don't.

– Falko – 2014-10-22T08:29:22.707

Thanks for pointer about 1else; it lets me squeeze out a char here and probably other places. But darn is it version-specific! Python 2.7.4 doesn't allow it. Are you using an online version with 2.7.8 or would I have to download it?

– xnor – 2014-10-22T09:02:08.180

@xnor: It's an offline installation. http://ideone.com/, e.g., fails to parse 1else as well.

– Falko – 2014-10-22T09:09:36.200

@FryAmTheEggman See my answer for how to use D and how to use Pyth's ternary. – isaacg – 2014-10-22T18:40:35.863

@FryAmTheEggman The two more changes needed to save 2 more characters are: 1. change <Z1 to !Z - we just want to test whether Z is 0, so using a not saves a character. 2. Use ? instead of |&, and move the conditional, Y in this case, in between the true case and the false case (just before hZ). – isaacg – 2014-10-22T18:50:51.070

6

J - 26 char

($:^:(<:@[`]`1:)^:(0<[)>:)

There is an alternate, more functional definition of Ackermann:

Ack 0 n = n+1
Ack m n = Iter (Ack (m-1)) n
Iter f 0 = f 1
Iter f n = f (Iter f (n-1))

It so happens that Iter is very easy to write in J, because J has a way of passing in the m-1 to Ack and also to define the initial value of Iter to be 1. Explained by explosion:

(                      >:)  NB. increment n
                ^:(0<[)     NB. if m=0, do nothing to n+1; else:
   ^:                       NB. iterate...
($:                      )  NB.   self ($: is recursion)
     (<:@[     )            NB.   with left arg m-1
          `]                NB.   n+1 times
            `1:             NB.   starting on 1

This relies on what J calls the gerund form of ^:—basically a way to have more control over all the bounds in a tacit (point-free) fashion.

At the REPL:

   3 ($:^:(<:@[`]`1:)^:(0<[)>:) 3
61
   ack =: ($:^:(<:@[`]`1:)^:(0<[)>:)
   (i.4) ack"0 table (i.11)
+-----+------------------------------------------+
|ack"0|0  1  2  3   4   5   6    7    8    9   10|
+-----+------------------------------------------+
|0    |1  2  3  4   5   6   7    8    9   10   11|
|1    |2  3  4  5   6   7   8    9   10   11   12|
|2    |3  5  7  9  11  13  15   17   19   21   23|
|3    |5 13 29 61 125 253 509 1021 2045 4093 8189|
+-----+------------------------------------------+
   6!:2 '3 ($:^:(<:@[`]`1:)^:(0<[)>:) 10'  NB. snugly fits in a minute
58.5831

We need to define ack by name to be able to put it in a table, because $: is a horrible, ugly beast and lashes out at anyone who attempts to understand it. It is self-reference, where self is defined as the largest verb phrase containing it. table is an adverb and so would love to become part of the verb phrase if you give it the chance, so you have to trap $: in a named definition to use it.


Edit: 24 char?

Years later, I found a solution which is two characters shorter.

(0&<~(<:@#~$:/@,1:^:)>:)

It's a lot slower, though: 3 ack 8 takes over a minute on my machine. This is because (1) I use a fold / instead of iteration, so J probably has to remember more things than usual, and (2) while 0&<~ performs the same calculation as (0<[), it actually gets executed n+1 times before taking the recursive step when invoking m ack n0&< happens to be idempotent, so it doesn't ruin the calculation, but n gets big fast and ack is highly recursive.

I am doubtful that a more powerful machine could push the new code under a minute, because this is a computer where the old code can find 3 ack 10 in less than 15 seconds.

algorithmshark

Posted 2014-10-22T04:38:29.693

Reputation: 8 144

5

C - 41 bytes

Nothing to it--the small limits mean that all the required values can be calculated in less than 1 second by naively following the function definition.

A(m,n){return!m?n+1:A(m-1,n?A(m,n-1):1);}


int main()
{
    int m,n;
    for(m = 0; m <= 3; m++)
    for(n = 0; n <= 10; n++)
    printf("%d %d %d\n", m,n,A(m,n));
    return 0;
}

feersum

Posted 2014-10-22T04:38:29.693

Reputation: 29 566

5

Javascript ES6 (34)

a=(m,n)=>m?a(m-1,n?a(m,n-1):1):n+1

Implementation:

a=(m,n)=>m?a(m-1,n?a(m,n-1):1):n+1
td[colspan="2"] input{width: 100%;}
<table><tbody><tr><td>m=</td><td><input id="m" type="number" value="0" /></td></tr><tr><td>n=</td><td><input id="n" type="number" value="0" /></td></tr><tr><td colspan="2"><input type="button" value="Calculate!" onclick="document.getElementById('out').value=a(document.getElementById('m').value, document.getElementById('n').value)" /></td></tr><tr><td colspan="2"><input id="out" disabled="disabled" type="text" /></td></tr></tbody></table>

kitcar2000

Posted 2014-10-22T04:38:29.693

Reputation: 2 689

4

JavaScript (ES6) - 34

A=(m,n)=>m?A(m-1,!n||A(m,n-1)):n+1

And a test:

> A=(m,n)=>m?A(m-1,!n||A(m,n-1)):n+1;s=new Date().getTime();console.log(A(3,10),(new Date().getTime() - s)/1000)
8189 16.441

core1024

Posted 2014-10-22T04:38:29.693

Reputation: 1 811

3

Coq, 40

nat_rec _ S(fun _ b n=>nat_iter(S n)b 1)

This is a function of type nat -> nat -> nat. Since Coq only allows the construction of total functions, it also serves as a formal proof that the Ackermann recurrence is well-founded.

Demo:

Welcome to Coq 8.4pl6 (November 2015)

Coq < Compute nat_rec _ S(fun _ b n=>nat_iter(S n)b 1) 3 10.
     = 8189
     : nat

Note: Coq 8.5, released after this challenge, renamed nat_iter to Nat.iter.

Anders Kaseorg

Posted 2014-10-22T04:38:29.693

Reputation: 29 242

2

Racket 67

(define(a m n)(if(= m 0)(+ n 1)(a(- m 1)(if(= n 0)1(a m(- n 1))))))

Matthew Butterick

Posted 2014-10-22T04:38:29.693

Reputation: 401

2

Mathematica, 46 bytes

0~a~n_:=n+1
m_~a~n_:=a[m-1,If[n<1,1,a[m,n-1]]]

Takes pretty much exactly a minute for a[3,10]. Note that Mathematica's default recursion limit is too small for a[3,8] and beyond (at least on my machine), but that can be fixed by configuring

$RecursionLimit = Infinity

Martin Ender

Posted 2014-10-22T04:38:29.693

Reputation: 184 808

1Wow, so are you saying that JS is more than 25 times faster than Mathematica ? – Optimizer – 2014-10-22T10:03:05.770

@Optimizer At least when it comes to recursion... I guess part if it is that it has to figure out each time which definition to use, and If being a function is even slower. – Martin Ender – 2014-10-22T10:05:21.790

1With memoization, it takes 0.07 seconds. I.e. m_~a~n_:=m~a~n=... – Mark Adler – 2014-10-23T02:11:46.530

@MarkAdler That's a really nice way to do memoisation in Mathematica! – Martin Ender – 2014-10-23T07:59:21.513

2

Haskell, 48 44 chars (36 for the list)

While not as short as the other Haskell solution, this one is notable because it expresses the Ackermann function as an infinite list, which I think is kinda neat. The result is an infinite list (of infinite lists) such that at position [m,n] it holds the value A(m,n).

The infinite list itself:

iterate(tail.(`iterate`1).(!!))[1..]

As a function (to comply with the specification):

i=iterate;m%n=i(tail.(`i`1).(!!))[1..]!!m!!n

The formulation was derived by observing that the general/common case for the Ackermann function is to use the value to the left as an index in the row above. The base case for this recursion (i.e. the leftmost column of a row, i.e. A(m,0)) is to use the second left-most value in the row above. The base case for that recursion is the A(0,n) = n+1 case, i.e. the first row is [1..].

Thus, we get

let a0 = [1..]
let a1 = tail $ iterate (a0 !!) 1  -- 'tail' because iterate starts by applying
let a2 = tail $ iterate (a1 !!) 1  -- the function 0 times
-- etc

Then we simply add another level of iteration based on that pattern, and do some pointless juggling.

FireFly

Posted 2014-10-22T04:38:29.693

Reputation: 7 107

You could alias iterate to a single letter name i.e. i=iterate;ack=i ... – proud haskeller – 2014-10-23T11:55:24.130

@proudhaskeller oh yeah, didn't think about that. Thanks! Borrowing your operator-name use as well. – FireFly – 2014-10-23T12:11:25.663

2

Javascript with lambdas, 34

A=(m,n)=>m?A(m-1,n?A(m,n-1):1):n+1

A tipical answer, can't make anything shorter.

Qwertiy

Posted 2014-10-22T04:38:29.693

Reputation: 2 697

2

Go, 260 243 240 122 bytes

I didn't see that the question allowed anon funcs.

far from competitive but i'm learning this language and i wanted to test it out.

func (m,n int)int{r:=0
switch{case m==0&&n!=0:r=n+1
case m!=0&&n==0:r=a(m-1,1)
case m!=0&&n!=0:r=a(m-1,a(m,n-1))}
return r}

use it like go run ack.go and then supply two numbers, m and n. if m>4 or n>30, execution time may be in excess of half a minute.

for m=3 n=11:

$ time go run ack
16381
real    0m1.434s
user    0m1.432s
sys     0m0.004s

edit: saved total 17 bytes by switching to switch over if/else and dot-imports

cat

Posted 2014-10-22T04:38:29.693

Reputation: 4 989

1You can do even better! switch 0 {case m:r=n+1 case n:r=a(m-1,1) default:r=a(m-1,a(m,n-1))} Go's switch statement is so beautifully flexible! – EMBLEM – 2016-05-14T02:11:38.510

@EMBLEM Thanks, it's been so long since I've written a line of Go, but I'm glad to see there are other Go-golfers about :D – cat – 2016-05-14T03:02:21.957

2

Tiny Lisp, 70 (out of competition)

This runs out of competition, as the language is newer than the question, and it also doesn't succeed to run the (A 3 10) as required in the question, due to a stack overflow.

(d A(q((m n)(i m(i n(A(s m 1)(A m(s n 1)))(A(s m 1)1))(s n(s 0 1))))))

This defines a function A which calculates the Ackermann function. Formatted:

(d A
   (q( (m n)
       (i m
          (i n
             (A (s m 1)
                (A m
                   (s n 1)
                 )
              ) 
             (A (s m 1)
                1
              )
           )
          (s n
             (s 0 1)
           )
        )
    ) )
 )

We are using all builtin macros (d (define) and q (quote) and i (if)) and one builtin function (s – subtract) here.

i executes its true part when the condition is a number > 0 (and otherwise the false part), so we don't have to do an explicit comparison here.

s is the only arithmetic operation available, we use it for the n-1/m-1, as well as as (s n (s 0 1)) for n+1.

Tiny lisp is using tail recursion optimization, but this only helps for the outer A call in the result, not for the A(m, n-1) call which is used for the parameters.

With my tiny lisp implementation in Ceylon on the JVM, it works up to (A 3 5) = 253, but it seems to break down when trying to calculate (A 2 125) directly (which should give the same result). If calculating that after (A 3 4) = 125, the JVM seems to got to optimize the functions enough to inline some intermediate function calls in my interpreter, allowing more recursion depth. Strange.

The reference implementation gets up to (A 3 5) = 253 and also (A 2 163) = 329, but doesn't succeed (A 2 164), and therefore even less (A 3 6) = (A 2 253).

Paŭlo Ebermann

Posted 2014-10-22T04:38:29.693

Reputation: 1 010

this might be competitive save for the whitespace and parenthesis ;) – cat – 2015-12-26T20:14:52.600

1

Tcl, 67 bytes

proc tcl::mathfunc::A m\ n {expr {$m?A($m-1,$n?A($m,$n-1):1):$n+1}}

Try it online!


Tcl, 77 bytes

proc A m\ n {expr {$m?[A [expr $m-1] [expr {$n?[A $m [expr $n-1]]:1}]]:$n+1}}

Try it online!

In the online compiler it fails to run due to time-out, but in a local Tcl interpreter it runs well. I profiled of each root call to A function, to see how much time the calculation took for each pair {m,n} subject to be tested:

m=0, n=0, A=1, time=3.5e-5 seconds
m=0, n=1, A=2, time=2e-6 seconds
m=0, n=2, A=3, time=8e-6 seconds
m=0, n=3, A=4, time=1e-6 seconds
m=0, n=4, A=5, time=2e-6 seconds
m=0, n=5, A=6, time=1e-6 seconds
m=0, n=6, A=7, time=1e-6 seconds
m=0, n=7, A=8, time=1e-6 seconds
m=0, n=8, A=9, time=1e-6 seconds
m=0, n=9, A=10, time=0.0 seconds
m=0, n=10, A=11, time=1e-6 seconds
m=1, n=0, A=2, time=4e-6 seconds
m=1, n=1, A=3, time=6e-6 seconds
m=1, n=2, A=4, time=1e-5 seconds
m=1, n=3, A=5, time=1.2e-5 seconds
m=1, n=4, A=6, time=1.5e-5 seconds
m=1, n=5, A=7, time=2e-5 seconds
m=1, n=6, A=8, time=2e-5 seconds
m=1, n=7, A=9, time=2.6e-5 seconds
m=1, n=8, A=10, time=3e-5 seconds
m=1, n=9, A=11, time=3e-5 seconds
m=1, n=10, A=12, time=3.3e-5 seconds
m=2, n=0, A=3, time=8e-6 seconds
m=2, n=1, A=5, time=2.2e-5 seconds
m=2, n=2, A=7, time=3.9e-5 seconds
m=2, n=3, A=9, time=6.3e-5 seconds
m=2, n=4, A=11, time=9.1e-5 seconds
m=2, n=5, A=13, time=0.000124 seconds
m=2, n=6, A=15, time=0.000163 seconds
m=2, n=7, A=17, time=0.000213 seconds
m=2, n=8, A=19, time=0.000262 seconds
m=2, n=9, A=21, time=0.000316 seconds
m=2, n=10, A=23, time=0.000377 seconds
m=3, n=0, A=5, time=2.2e-5 seconds
m=3, n=1, A=13, time=0.000145 seconds
m=3, n=2, A=29, time=0.000745 seconds
m=3, n=3, A=61, time=0.003345 seconds
m=3, n=4, A=125, time=0.015048 seconds
m=3, n=5, A=253, time=0.059836 seconds
m=3, n=6, A=509, time=0.241431 seconds
m=3, n=7, A=1021, time=0.971836 seconds
m=3, n=8, A=2045, time=3.908884 seconds
m=3, n=9, A=4093, time=15.926341 seconds
m=3, n=10, A=8189, time=63.734713 seconds

It fails for the last pair {m,n}={3,10}, as it takes a very little more than one minute.

For higher values of m, it will be needed to increase the recursionlimit value.


I coult get it shorter to 65 bytes, but it will not meet the question's requirement "Your function must be able to find the value of A(m,n) for m ≤ 3 and n ≤ 10 in less than a minute.". Without the {} it will timeout on TIO and not do the demo of the last two entries.

Tcl, 65 bytes

proc tcl::mathfunc::A m\ n {expr $m?A($m-1,$n?A($m,$n-1):1):$n+1}

Try it online!

sergiol

Posted 2014-10-22T04:38:29.693

Reputation: 3 055

1

brainfuck, 90 bytes

>>>>+>,>,<<[>[>[-[->>>+<<<]<[->+>>+<<<]>-[-<+>]>+>>>>>]<[->+>>]]<[>>+[-<<<+>>>]<<-]<<<]>>.

Try it online!

Assumes an implementation with arbitrary sized cell size, with IO as numbers. -6 bytes if you don't mind using negative cells.

Finishes in about 30 seconds for 3,8 in the linked interpreter, provided you tick the correct settings. Type inputted numbers prepended with \s, e.g. 3,9 is \3\9.

Jo King

Posted 2014-10-22T04:38:29.693

Reputation: 38 234

1

Haskell: 81 69 bytes

a::Int->Int->Int
a 0 n=n+1
a m 0=a (m-1) 1
a m n=a (m-1) a m (n-1)

a 3 10 takes about 45 seconds.

SophR

Posted 2014-10-22T04:38:29.693

Reputation: 19

1this is code golf, so you should try to have the shortest code possible. for example, remove unnecessary spaces and the explicit type – proud haskeller – 2014-10-22T13:34:52.577

you're also missing the parens on the fourth line – proud haskeller – 2014-10-22T13:36:06.350

1

R - 54 52

I've used this as an excuse to try and get my head around R, so this is probably really badly done:)

a=function(m,n)"if"(m,a(m-1,"if"(n,a(m,n-1),1)),n+1)

Example run

> a(3,8)
[1] 2045

I get a stack overflow for anything beyond that

T-SQL- 222

I thought I would try to get T-SQL to do it as well. Used a different method because recursion isn't that nice in SQL. Anything over 4,2 bombs it.

DECLARE @m INT=4,@n INT=1;WITH R AS(SELECT 2 C, 1 X UNION ALL   SELECT POWER(2,C),X+1FROM R)SELECT IIF(@m=0,@n+1,IIF(@m=1,@n+2,IIF(@m=2,2*@n+3,IIF(@m=3,POWER(2,@n+3)-3,IIF(@m=4,(SELECT TOP(1)C FROM R WHERE x= @n+3)-3,-1)))))

MickyT

Posted 2014-10-22T04:38:29.693

Reputation: 11 735

for your R submisson, looks like you don't need the {} although there's no helping the stack overflow limit, since R doesn't have TCO... – Giuseppe – 2018-03-21T12:45:01.190

@Giuseppe thanks ... in my defense, I was new to it then :) – MickyT – 2018-03-21T17:25:04.277

1

(non-competing) UGL, 31 30 bytes

iiRuldr%l%lR$d%rd:u%d:%+uRu:ro

Input separated by newlines.

Try it online!

(It has been implemented as a standard example in the interpreter.)

Leaky Nun

Posted 2014-10-22T04:38:29.693

Reputation: 45 011

1

(non-competing) Pyth, 15 bytes

M?GgtG?HgGtH1hH

Try it online! (sample usage of the function g3T added, which means g(3,10))

Leaky Nun

Posted 2014-10-22T04:38:29.693

Reputation: 45 011

1

Julia, 34 31 28 bytes

m\n=m>0?~-m\(n<1||m\~-n):n+1

This is a named anonymous function. It is a straightforward implementation of the recursive definition, abusing Julia's ability to redefine operators.

Try it online!

Dennis

Posted 2014-10-22T04:38:29.693

Reputation: 196 637

0

J : 50

>:@]`(1$:~<:@[)`(<:@[$:[$:_1+])@.(0>.[:<:@#.,&*)M.

Returns in a fraction of a second for 0...3 vs 0 ... 10:

   A=:>:@]`(1$:~<:@[)`(<:@[$:[$:_1+])@.(0>.[:<:@#.,&*)M.
   timespacex 'res=:(i.4) A"0 table (i.11)'
0.0336829 3.54035e6
   res
┌───┬──────────────────────────────────────────┐
│A"0│0  1  2  3   4   5   6    7    8    9   10│
├───┼──────────────────────────────────────────┤
│0  │1  2  3  4   5   6   7    8    9   10   11│
│1  │2  3  4  5   6   7   8    9   10   11   12│
│2  │3  5  7  9  11  13  15   17   19   21   23│
│3  │5 13 29 61 125 253 509 1021 2045 4093 8189│
└───┴──────────────────────────────────────────┘

PS: the "0 serves to make A work on each single element, instead of gobbling up the left and right array, and generating length errors. But it's not needed for eg. 9 = 2 A 3 .

jpjacobs

Posted 2014-10-22T04:38:29.693

Reputation: 3 440

http://codegolf.stackexchange.com/a/40174/48934 You have been beaten! – Leaky Nun – 2016-03-31T04:15:29.647

0

APL, 31

{⍺=0:⍵+1⋄⍵=0:1∇⍨⍺-1⋄(⍺-1)∇⍺∇⍵-1}

Pretty straightforward. Uses the ⍨ character once to save one byte by reversing arguments. Takes m as the left argument and n as the right argument.

TryAPL.org

Shujal

Posted 2014-10-22T04:38:29.693

Reputation: 687

0

Ruby, 65

h,a={},->m,n{h[[m,n]]||=m<1?(n+1):(n<1?a[m-1,1]:a[m-1,a[m,n-1]])}

Explanation

This is a pretty straightforward translation of the algorithm given in the problem description.

  • Input is taken as the arguments to a lambda. Two Integers are expected.
  • For speed and avoiding stack-overflow errors, answers are memoized in the Hash h. The ||= operator is used to calculate a value that wasn't previously calculated.

a[3,10] is calculated in ~0.1 sec on my machine.

Here's an ungolfed version

h = {}
a = lambda do |m,n|
  h[[m,n]] ||= if m < 1 
    n + 1
  elsif n < 1
    a[m-1,1]
  else
    a[m-1,a[m,n-1]]
  end
end

britishtea

Posted 2014-10-22T04:38:29.693

Reputation: 1 189

a[3,10] throw a SystemStackError on my machine... – TuxCrafting – 2016-06-18T15:44:56.323

Golf nitpicks: You could change m<1?(n+1):(n<1?a[m-1,1]:a[m-1,a[m,n-1]]) to m<1?n+1:a[m-1,n<1?1:a[m,n-1]] – Simply Beautiful Art – 2017-11-06T23:32:40.027

0

Ceylon, 88 87 85

alias I=>Integer;I a(I m,I n)=>m<1then n+1else(n<1then a(m-1,1)else a(m-1,a(m,n-1)));

This is a straightforward implementation. Formatted:

alias I => Integer;
I a(I m, I n) =>
        m < 1
        then n + 1
        else (n < 1
            then a(m - 1, 1)
            else a(m - 1, a(m, n - 1)));

The alias saves just one byte, without it (with writing Integer instead of I) we would get to 86 bytes. Another two bytes can be saved by replacing == 0 by < 1 twice.

With the default settings of ceylon run, it will work up to A(3,12) = 32765 (and A(4,0) = 13), but A(3,13) (and therefore also A(4,1)) will throw a stack overflow error. (A(3,12) takes about 5 seconds, A(3,11) about 3 on my computer.)

Using ceylon run-js (i.e. running the result of compiling to JavaScript on node.js) is a lot slower (needs 1 min 19 s for A(3,10)), and breaks already for A(3, 11) with a »Maximum call stack size exceeded« (using default settings) after running for 1 min 30 s.


Ceylon without recursion, 228

As a bonus, here is a non-recursive version (longer, of course, but immune to stack overflows – might get an out-of-memory error at some point).

import ceylon.collection{A=ArrayList}Integer a(Integer[2]r){value s=A{*r};value p=s.addAll;while(true){if(exists m=s.pop()){if(exists n=s.pop()){if(n<1){p([m+1]);}else if(m<1){p([n-1,1]);}else{p([n-1,n,m-1]);}}else{return m;}}}}

Formatted:

import ceylon.collection {
    A=ArrayList
}

Integer a(Integer[2] r) {
    value s = A { *r };
    value p = s.addAll;
    while (true) {
        if (exists m = s.pop()) {
            if (exists n = s.pop()) {
                if (n < 1) {
                    p([m + 1]);
                } else if (m < 1) {
                    p([n - 1, 1]);
                } else {
                    p([n - 1, n, m - 1]);
                }
            } else {
                // stack is empty
                return m;
            }
        }
    }
}

It is quite slower on my computer than the recursive version: A(3,11) takes 9.5 seconds, A(3,12) takes 34 seconds, A(3,13) takes 2:08 minutes, A(3,14) takes 8:25 minutes. (I originally had a version using lazy iterables instead of the tuples I now have, which was even much slower, with the same size).

A bit faster (21 seconds for A(3,12)) (but also one byte longer) is a version using s.push instead of s.addAll, but that needed to be called several times to add multiple numbers, as it takes just a single Integer each. Using a LinkedList instead of an ArrayList is a lot slower.

Paŭlo Ebermann

Posted 2014-10-22T04:38:29.693

Reputation: 1 010

0

Mouse-2002, 99 83 bytes

$Y1%j:j.0=m:2%k:k.0=n:m.n.>[k.1+!|m.n.<[#Y,j.1-,1;|m.n.*0=[#Y,j.1-,#Y,j.,k.1+;;]]]@

cat

Posted 2014-10-22T04:38:29.693

Reputation: 4 989

0

Java, 274 bytes

import java.math.*;class a{BigInteger A(BigInteger b,BigInteger B){if(b.equals(BigInteger.ZERO))return B.add(BigInteger.ONE);if(B.equals(BigInteger.ZERO))return A(b.subtract(BigInteger.ONE),BigInteger.ONE);return A(b.subtract(BigInteger.ONE),A(b,B.subtract(BigInteger.ONE)));}}

It calculates A(3,10) in a few seconds, and given infinite memory and stack space, it can calculate any combination of b and B as long as the result is below 22147483647-1.

user8397947

Posted 2014-10-22T04:38:29.693

Reputation: 1 242

I know it's been a while, but you can golf this to 185 bytes: import java.math.*;BigInteger A(BigInteger b,BigInteger B){return b.equals(B.ZERO)?B.add(B.ONE):B.equals(B.ZERO)?A(b.subtract(B.ONE),B.ONE):A(b.subtract(B.ONE),A(b,B.subtract(B.ONE)));} – Kevin Cruijssen – 2018-03-21T10:28:05.940