アッカーマン関数


35

アッカーマン関数は、原始再帰ではない、計算可能な合計関数の最も単純な例の1つであることで注目に値します。

A(m,n)2つの非負整数を取り込む定義を使用します。

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

実装できます

  • 入力として2つの整数を受け取り、整数を返す名前付き関数または匿名関数、または
  • STDINで2つのスペースまたは改行で区切られた整数を取得し、結果をSTDOUTに出力するプログラム。

ライブラリのアッカーマン関数または超指数関数が存在する場合は使用できませんが、他のライブラリのその他の関数は使用できます。正規の累乗が許可されます。

関数は、A(m,n)m≤3およびn≤10の値を1分以内に検出できる必要があります。少なくとも理論的には、他の入力で終了する必要があります。無限のスタックスペース、ネイティブのBigint型、および任意の長い期間が与えられた場合、答えを返します。編集:言語の制限の深さがデフォルトの再帰の深さである場合は、文字コストなしで再設定できます。

最短の文字数での提出が勝ちです。

答えを確認するための値を次に示します。

  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...

15
これは以前どのように尋ねられなかったのですか?
カルビンの趣味14年

9
私はこの作るためにもっと楽しくなると思う最速のコードを
SP3000

22
ここには課題がないため、ダウン投票。明確な答え-その定義に正確に従って関数を単純に実装するだけ-は常に最良の答えになるでしょう。そこで質問は、「アッカーマンの関数の明白な表現で文字数が最も少ない言語はどれですか?」です。真の勝者はプログラミング言語であり、その中に明白なプログラムを書いた人ではありません。
デビッドリチャービー14年

1
私の言語の再帰制限が低すぎて計算できず、他の言語A(3,8)と同様に素朴に計算できない場合はどうなりますか?非再帰的なソリューションを考え出す必要がありますか、またはこれらの場合に「無限のスタックスペースを想定」することもできますか?確かに、1分以内に終了します。
マーティンエンダー14年

5
@DavidRicherby「明白な答え[...]は常に最良の答えになるでしょう。」これはすべての言語に当てはまるわけではありません。私の母国語での例を持っているだけで少し汚い気がしますが、アッカーマンを表現する方法は複数あり、いくつかの言語ではその事実を利用することで節約できます。これが私の挑戦の意図でした。
algorithmshark 14年

回答:


7

ピス、19

DaGHR?atG?aGtHH1GhH

を定義しaます。これは、アッカーマン関数として機能します。これには、公式のpythコンパイラが今日まで計算を許可していたよりも高い再帰深度が必要なa 3 10ので、再帰深度を増やしました。これは言語の変更ではなく、コンパイラの変更です。

テスト:

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

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

説明:

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)

基本的に、最初にGH + 1を再帰するか返すかの真理値を条件とします。再帰的である場合、最初の引数は常にG-1であり、2番目の引数としてH使用するかa(G,H-1)2番目の引数として使用するかの真理値を条件とし1ます。


現代Pyth(私はこれがこの挑戦の後に追加されましたと仮定)で、私はあなたが多かれ少なかれ変更することができると思うDaGHRMaしますg。(?変更の引数の順序は?)
リン

@Maurisはい、M代わりに使用できます?。はい、引数の順序が変更されました。条件、true、falseになりました。それは真実、条件、偽でした。
isaacg

@Lynn楽しいPyth履歴の事実は:この質問は実際には(少なくとも)の変化にPyth約2つの物事isaacg影響再帰限度する変更をM
FryAmTheEggman

23

ハスケル、35

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

これは演算子関数を定義します%

これは、非ゼロのm%n(がaackerman関数である)mがに(m-1)%適用されることに注意することで機能n+11ます。例えば、3%2として定義されている2%(3%1)である2%(2%(3%0))、これはあります2%(2%(2%1))


あまりにも悪いので、優先順位の0%n代わりに使用することはできませんn+1
誇りに思ってhaskeller 14


うわー、これは長い間間違っていました、そして、私を含む誰も気づきませんでしたか?よくできました。だから私は間違った答えの最初のバージョンを間違ってコピーしたようです。
誇りに思っているhaskeller

12

GolfScript(30)

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

オンラインデモ

1>(特別な場合A(1, n))なしでは、A(3, 10)テストしたコンピューターで計算するのに9分かかります。その特別なケースでは、オンラインデモの所要時間は10秒未満で十分です。

これ定義の単純な翻訳ではないことに注意してください。再帰の深さはによって制限されmます。

解剖

{             # 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

CJamでは、必要ありません1>。除去後(および変更if?)、コンピューティングは、3 10 AJavaインタプリタとオンライン通訳と6秒で110秒かかります。
デニス14年


6

JavaScriptを、ES6、41の 34バイト

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

最新のFirefoxコンソールでこれを実行し、それが呼び出された関数が作成されますfあなたが異なる値で呼び出すことができるmn同様に

f(3,2) // returns 29

または

最新の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>


Chromeでこれを0,1でテストしても結果はありません。
Nzall

3
読んでください、これはES6による最新のFirefoxでのみ動作します
オプティマイザー14年

すごい... 34バイトの4つの実質的に同一のJSソリューションがあります。私はそれを見たことがありません。
ETHproductions

6

パイソン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

(xnorへのクレジット!)

より読みやすくなりましたが、もう1文字あります。

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

sys.setrecursionlimit(10000)結果を得るために設定しなければならなかったというわけではありませんA(3,10)。論理的なインデックス付けを使用したそれ以上のゴルフは、再帰深度が劇的に増加するため機能しませんでした。


で構文エラーが表示されます1elsee数字はのように書くことができるため、開始文字はパーサーに問題を引き起こし1e3ます。
xnor 14年

保存への切り替えは数文字and/orA=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n
XNOR

@xnor:ヒントをありがとう!解析の問題の問題については、この説明を参照してください。Python 2.7.8は受け入れますが1else、他のほとんどのバージョンは受け入れません。
ファルコ14年

についてのポインタをありがとう1else; ここや他の場所でイワナを絞ることができます。しかし、それはバージョン固有です!Python 2.7.4では許可されていません。2.7.8のオンラインバージョンを使用していますか、それをダウンロードする必要がありますか?
xnor 14年

@xnor:オフラインインストールです。ideone.comなど1elseも解析できません。
ファルコ14年

6

J-26文字

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

アッカーマンには、より機能的な代替定義があります。

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))

とてもそれが起こるIterJを渡すの方法があるので、Jに非常に簡単に書くことですm-1Ackの初期値を定義し、また、Iter爆発によって1を説明しました:

(                      >:)  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

これは、J ^:が動名詞形式と呼ぶものに依存しています。基本的には、暗黙の(ポイントフリー)方法ですべての境界をより詳細に制御する方法です。

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

ackテーブルに入れることができるように名前で定義する必要があります。なぜなら、それ$:は恐ろしくugい獣であり、それを理解しようとする人をるからです。それは自己参照であり、自己はそれを含む最大の動詞句として定義されます。tableは副詞であるため、機会があれば動詞句の一部になりたいので、それ$:を使用するには名前付き定義にトラップする必要があります。


編集:24文字?

数年後、私は2文字短い解決策を見つけました。

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

ただし、処理はかなり遅くなります3 ack 8。私のマシンでは1分以上かかります。この私が倍使用(1)ためである/一方、Jは、おそらく通常よりも多くの事を覚えている必要があり、(2)ので、反復の代わりに0&<~行って同じ計算として(0<[)、それが実際に実行されます、n+1回を再帰的なステップを取る前に呼び出すときにm ack n- 0&<起こりますべき等であるため、計算を台無しにしませんがn、大きく速くなり、ack非常に再帰的です。

これは古いコードが3 ack 1015秒未満で見つけることができるコンピューターであるため、より強力なマシンが1分以内に新しいコードをプッシュできるかどうかは疑わしいです。


5

C-41バイト

それには何もありません。小さな制限は、関数定義を単純に追跡することで、必要なすべての値を1秒未満で計算できることを意味します。

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

5

Javascript ES6(34)

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

実装:

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>


4

JavaScript(ES6)-34

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

そしてテスト:

> 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

3

Coq、40

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

これはtypeの関数ですnat -> nat -> nat。Coqは全関数の構築のみを許可するため、Ackermannの再発が十分に根拠があることの正式な証拠としても機能します。

デモ:

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

注:このチャレンジの後にリリースされたCoq 8.5は、に名前が変更さnat_iterれましたNat.iter



2

Mathematica、46バイト

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

にほぼ正確に1分かかりますa[3,10]。Mathematicaのデフォルトの再帰制限はa[3,8](少なくとも私のマシン上では)小さすぎますが、設定することで修正できることに注意してください

$RecursionLimit = Infinity

1
うわー、だからあなたはJSがMathematicaより25倍以上速いと言っていますか?
オプティマイザー14年

@Optimizer少なくとも再帰に関しては...どの定義を使用するかを毎回把握する必要がありIf、関数であることはさらに遅いということである場合、私は部分を推測します。
マーティンエンダー14年

1
メモ化では、0.07秒かかります。つまりm_~a~n_:=m~a~n=...
マーク・アドラー

@MarkAdlerこれはMathematicaでメモ化を行うのに本当に良い方法です!
マーティンエンダー14年

2

ラムダ付きのJavaScript、34

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

典型的な答えは、これ以上短くすることはできません。


2

Haskell、48 44文字(リストでは36文字)

他のHaskellソリューションほど短くはありませんが、これはアッカーマン関数を無限リストとして表現しているため注目に値します。結果は、位置[m、n]で値A(m、n)を保持するような(無限リストの)無限リストです。

無限リスト自体:

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

機能として(仕様に準拠するため):

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

公式は、アッカーマン関数の一般的/一般的なケースでは、左の値を上の行のインデックスとして使用することを観察することにより導き出されました。この再帰の基本ケース(つまり、行の左端の列、つまりA(m、0))は、上の行の左から2番目の値を使用します。その再帰の基本ケースはA(0、n)= n + 1ケースです[1..]。つまり、最初の行はです。

したがって、

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

次に、そのパターンに基づいて別のレベルの反復を追加し、無意味なジャグリングを行います。


エイリアスでしiterateすなわち単一文字の名前にi=iterate;ack=i ...
誇りhaskeller

@proudhaskellerそうそう、それについて考えなかった。ありがとう!演算子名の借用も同様に使用します。
FireFly 14年

2

Tiny Lisp、70(非競合)

言語は質問よりも新しいため、これは競合を使い果たし(A 3 10)ます。また、スタックオーバーフローのため、質問で要求されたとおりに実行することもできません。

(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))))))

これはA、アッカーマン関数を計算する関数を定義します。フォーマット済み:

(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)
           )
        )
    ) )
 )

ここでは、すべての組み込みマクロ(d(define)およびq(quote)およびi(if))と1つの組み込み関数(s-減算)を使用しています。

i 条件が数値> 0(およびそれ以外の場合は偽の部分)である場合、その真の部分を実行するため、ここで明示的な比較を行う必要はありません。

s使用可能な唯一の算術演算は、n-1/ m-1だけでなく/にも使用(s n (s 0 1))n+1ます。

Tiny Lispは末尾再帰最適化を使用していますが、これはA結果の外側の呼び出しにのみ役立ちA(m, n-1)、パラメーターに使用される呼び出しには役立ちません。

私の小さなLispの実装 JVM上セイロンでは、それは、最大動作します(A 3 5) = 253が、計算しようとしたときにブレークダウンしているようだ(A 2 125)(同じ結果を与える必要があります)を直接。それを計算した後(A 3 4) = 125、JVMは、インタープリターでいくつかの中間関数呼び出しをインライン化するのに十分な関数を最適化するようになり、再帰の深さが増加します。奇妙な。

リファレンス実装では、最大取得(A 3 5) = 253しても(A 2 163) = 329、しかし、成功していない(A 2 164)にも少ないので、と(A 3 6) = (A 2 253)


これは、空白と括弧を節約するための競争力があるかもしれません;)
cat

2

Go、260 243 240 122バイト

私は質問がアノンファンクを許可することを見ませんでした。

競争とはほど遠いですが、この言語を学んでいるので、試してみたいと思いました。

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}

のように使用しgo run ack.go、2つの数字を指定mnます。m> 4またはn> 30の場合、実行時間は30分を超える場合があります。

のためにm=3 n=11

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

編集switchオーバーif/elseインポートとドットインポートに切り替えて、合計17バイトを保存しました


1
さらに改善できます!switch 0 {case m:r=n+1 case n:r=a(m-1,1) default:r=a(m-1,a(m,n-1))}Goのswitchステートメントはとても柔軟です!
エンブレム

@EMBLEMありがとう、Goの行を書いてから長い時間が経ちましたが、他のGo-Golferが:D
cat

1

Haskell:81 69バイト

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 約45秒かかります。


1
これはコードゴルフですので、できるだけ短いコードを使用するようにしてください。たとえば、不要なスペースと明示的なタイプを削除します
誇り高いhaskeller 14年

あなたはまた、4行目括弧不足している
誇りhaskeller




1

R- 54 52

私はこれを口実として使用して、Rを回避しようと試みました。

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

実行例

> a(3,8)
[1] 2045

それを超えるとスタックオーバーフローが発生します

T-SQL- 222

T-SQLでも同様にできるようにしようと思った。再帰はSQLではそれほど優れていないため、別の方法を使用しました。4,2を超えるものはそれを爆撃します。

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)))))

{}RにはTCOがないため、スタックオーバーフロー制限の助けはありませんが、Rサブミッションの場合は必要ないように見えます...-
Giuseppe

@ジュゼッペありがとう...私の防衛では、私はそれが初めてだった:)
MickyT

1

brainfuck、90バイト

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

オンラインでお試しください!

IOを数値とする、任意のサイズのセルサイズの実装を想定しています。負のセルを使用しても構わない場合は-6バイト。

正しい設定にチェックを入れると、リンクされたインタープリターで3,8秒間約30秒で終了します。で先頭に追加入力番号入力\Sを、例えば3,9あります\3\9


1

Tcl、67バイト

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

オンラインでお試しください!


Tcl、77バイト

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

オンラインでお試しください!

オンラインコンパイラではタイムアウトのため実行に失敗しますが、ローカルTclインタープリターでは正常に実行されます。A関数への各ルートコールのプロファイルを作成し、{m,n}テスト対象の各ペアの計算にかかった時間を確認しました。

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

最後のペアでは失敗します {m,n}={3,10}では1分以上かかる。

の値が大きい場合mrecursionlimit値を増やす必要があります。


私はそれを65バイトに短くしますが、質問の要件「あなたの関数は1分未満でm≤3およびn≤10のA(m、n)の値を見つけられる必要があります」を満たしません。{}これがないと、TIOでタイムアウトし、最後の2つのエントリのデモを実行しません。

Tcl、65バイト

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

オンラインでお試しください!


0

J:50

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

0 ... 3対0 ... 10の場合、1秒未満で戻ります。

   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: "0は、左右の配列をゴブリングして長さエラーを生成する代わりに、Aを各単一要素で動作させるのに役立ちます。しかし、例えば9 = 2 A 3の場合は必要ありません。



0

APL、31

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

とても簡単です。⍨文字を1回使用して、引数を逆にして1バイトを保存します。左引数としてmを、右引数としてnを取ります。

TryAPL.org


0

ルビー、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]])}

説明

これは、問題の説明で与えられたアルゴリズムの非常に簡単な翻訳です。

  • 入力は、ラムダへの引数として取得されます。2 Integer秒が予想されます。
  • 速度とスタックオーバーフローエラーを回避するために、回答はにメモされていHash hます。||=オペレータは、以前に計算されなかった値を計算するために使用されます。

a[3,10] 私のマシンでは〜0.1秒で計算されます。

これは、無料版です

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

a[3,10]私のマシンでSystemStackErrorをスローします...
TuxCrafting

ゴルフnitpicks:あなたは変更される可能性m<1?(n+1):(n<1?a[m-1,1]:a[m-1,a[m,n-1]])m<1?n+1:a[m-1,n<1?1:a[m,n-1]]
単純に美しいアート


0

Java、274バイト

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

これは、計算A(3,10)数秒で、そして無限のメモリとスタック空間を考えると、それは、任意の組み合わせを計算することができますbし、B限り、結果は2未満であるよう2147483647 -1。


私はそれがしばらくしている知っているが、あなたがするために、このゴルフができ185バイト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)));}
ケビンCruijssen

0

セイロン、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)));

これは簡単な実装です。フォーマット済み:

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)));

エイリアスは1バイトだけを保存しますが、エイリアスがなければ(書き込みではIntegerなくI)86バイトになります。2回置き換えると== 0、さらに2バイト節約できます< 1

のデフォルト設定ではceylon runA(3,12) = 32765(およびA(4,0) = 13)まで機能しますが、A(3,13)(したがってA(4,1))スタックオーバーフローエラーがスローされます。(私のコンピューターでA(3,12)は約5秒、A(3,11)約3 秒かかります。)

使用してceylon run-js多くの、より遅い(ニーズ1分19秒(つまりNode.jsの上のJavaScriptにコンパイルの結果を実行している)A(3,10)すでに)、および休憩のためのA(3, 11)1のために実行した後»最大コールスタックサイズを超えたと«(デフォルト設定を使用)最小30秒


再帰のないセイロン、228

ボーナスとして、ここに非再帰バージョンがあります(もちろん、より長いですが、スタックオーバーフローの影響を受けません。ある時点でメモリ不足エラーが発生する可能性があります)。

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

フォーマット済み:

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

私のコンピューターでは、再帰バージョンよりもかなり遅いです:A(3,11)9.5秒、A(3,12)34秒、A(3,13)2:08分かかります。A(3,14) 8:25分かかります。(元々、現在持っているタプルの代わりにレイジーイテラブルを使用したバージョンがありましたが、同じサイズでさらに遅くなりました)。

少し高速(の場合は21秒A(3,12))(ただし、1バイト長い)はのs.push代わりに使用するバージョンですが、s.addAll複数の数値を追加するために複数回呼び出す必要があります。ArrayListの代わりにLinkedListを使用すると、かなり遅くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.