Ackermann 기능


34

Ackermann 함수는 원시 재귀 적이 지 않은 계산 가능한 총 함수 중 가장 간단한 예 중 하나로 유명합니다.

우리는 A(m,n)음이 아닌 두 정수 를 취하는 정의를 사용합니다 .

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

구현할 수 있습니다

  • 두 개의 정수를 입력으로 사용하여 정수를 반환하는 명명 된 또는 익명 함수
  • STDIN에서 공백 또는 개행으로 구분 된 두 정수를 가져 와서 결과를 STDOUT에 인쇄하는 프로그램.

라이브러리에서 Ackermann 함수 또는 hyperexponentiation 함수 (있는 경우)를 사용할 수 없지만 다른 라이브러리에서 다른 함수를 사용할 수 있습니다. 정기적 인 지수가 허용됩니다.

함수는 A(m,n)1 분 이내에 m ≤ 3 및 n ≤ 10 의 값을 찾을 수 있어야합니다 . 적어도 이론적 으로는 다른 입력에서 끝나야합니다. 무한 스택 공간, 기본 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
이것은 이전에 어떻게 요청되지 않았습니까?
Calvin 's Hobbies


22
여기에 도전이 없기 때문에 다운 보팅. 정의에 따라 정확히 순진하게 기능을 구현하는 명백한 답변은 항상 최고의 답변이 될 것입니다. 문제는 "어 커맨의 기능을 명백히 표현할 때 언어가 가장 적은 문자는 무엇입니까?"입니다. 진정한 승자는 프로그래밍 언어이며 명확한 프로그램을 작성한 사람이 아닙니다.
David Richerby

1
언어의 재귀 제한이 계산하기에 너무 낮고 A(3,8)다른 언어 처럼 순진하게 초과하면 어떻게됩니까? 비 재귀 솔루션을 만들어야합니까, 아니면이 경우 "무한 스택 공간을 가정"할 수 있습니까? 꽤 확신합니다. 1 분 안에 종료됩니다.
Martin Ender

5
@DavidRicherby "명백한 대답 [...]은 항상 최고의 대답이 될 것입니다." 모든 언어에 해당되는 것은 아닙니다. 나는 모국어로 예를 들어서 조금 더럽다고 느끼지만, Ackermann을 표현하는 방법에는 여러 가지가 있으며 일부 언어에서는 그 사실을 사용하여 저축을 얻을 수 있습니다. 이것이 도전에 대한 나의 의도였다.
algorithmshark

답변:


7

피 이스 , 19

DaGHR?atG?aGtHH1GhH

aAckermann 함수로 작동하는을 정의합니다 . 오늘까지 계산할 수있는 공식 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이며 두 번째 인수 H로 사용할지 a(G,H-1)또는 두 번째 인수 로 사용할지의 실제 값에 따라 달라집니다 1.


현대 Pyth에서 내가 할 수있는 더 많거나 적은 변화를 생각한다 (I는이 공격 후 추가 된 가정) DaGHRMag. ( ?변경에 대한 논쟁의 순서를 했습니까 ?)
Lynn

@Mauris 예, M대신 사용할 수 있으며 예, ?인수 순서가 변경되었습니다. 이제는 조건입니다. 참, 거짓. 사실, 조건, 거짓이었다.
isaacg 2016

@Lynn Fun Pyth history facts :이 질문은 실제로 isaacg가 Pyth에 대해 (적어도) 두 가지를 변경하도록 영향을 미쳤습니다 : 재귀 한계로의 변경M !
FryAmTheEggman

23

하스켈, 35

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

이것은 연산자 함수를 정의합니다 %.

이것은 0 이 아닌 에 대한 (ackerman 함수는 m%n어디에 a있습니까) 시간 m(m-1)%적용 된다는 것을 알면 작동 n+1합니다 1. 예를 들어, 3%2로 정의 2%(3%1)되는 2%(2%(3%0)), 이는 인2%(2%(2%1))


너무 나쁘다. 우선 순위 때문에 0%n대신 사용할 수 없다n+1
자랑스러운 haskeller


와우, 이것은 오랫동안 잘못되었고, 나 자신을 포함하여 아무도 눈치 채지 못했습니까? 잘 했어. 그래서 실수로 잘못되었거나 아마도 효과가 있다고 생각했기 때문에 첫 번째 버전의 답변을 실수로 복사 한 것 같습니다.
자랑스런 Haskeller

12

골프 스크립트 (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 A자바 인터프리터와 온라인 인터프리터 110 초 육초 걸립니다.
Dennis

7

이진 람다 미적분 , 54 비트 = 6.75 바이트

16 진 덤프 :

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

이진 :

000101100000011100101101100010000000011100101111011010

이것은 λ m 입니다. mg . λ N . g ( N g 1)) (λ N . λ F . λ X . F ( N F (X) )), 모든 숫자로 표현되는 경우 교회 부호 .


6

자바 스크립트, ES6, 41 34 바이트

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

최신의 파이어 폭스 콘솔에서이 작업을 실행하고라는 함수를 만듭니다 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
PL 읽기, 이것은 ES6으로 인해 최신 Firefox에서만 작동합니다
Optimizer

와우 ... 우리는 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). 재귀 깊이가 급격히 증가하여 논리적 인덱싱을 사용한 추가 골프는 작동하지 않았습니다.


에 구문 오류가 발생합니다 1else. e숫자는 다음과 같이 쓸 수 있기 때문에 시작 문자 는 파서에 문제를 일으 킵니다 1e3.
xnor

다음으로 전환하는 몇 가지 문자를 저장했습니다 and/or.A=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n
xnor

@ xnor : 팁 주셔서 감사합니다! 구문 분석 문제 문제에 대해서는 이 토론 을 참조하십시오 . Python 2.7.8은을 허용 1else하지만 대부분의 다른 버전은 허용 하지 않습니다.
Falko

에 대한 포인터 주셔서 감사합니다 1else; 여기 와 다른 곳 에서 숯을 짜낼 수 있습니다. 그러나 버전마다 다릅니다! 파이썬 2.7.4는 그것을 허용하지 않습니다. 2.7.8의 온라인 버전을 사용 중입니까, 아니면 다운로드해야합니까?
xnor

@xnor : 오프라인 설치입니다. 예를 들어 ideone.com도 구문 분석에 실패합니다 1else.
Falko

6

J-26 자

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

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

너무 그렇게 IterJ는 전달의 방법이 있기 때문에, J에서 쓰기에 매우 쉽습니다 m-1에를 Ack또한의 초기 값 정의 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가 gerund 형식이라고 부르는 것에 의존합니다. ^:기본적으로 모든 경계를 암묵적인 (무점) 방식으로 더 많이 제어 할 수있는 방법입니다.

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는 테이블에 넣을 수 있도록 이름 으로 정의해야 합니다. 왜냐하면 $:끔찍하고 못생긴 짐승이며 그것을 이해하려고 시도하는 사람에게 속이기 때문입니다. self-reference는 self가 그것을 포함하는 가장 큰 동사구로 정의됩니다. table는 부사이므로, 기회를 주면 동사구의 일부가되기를 원하므로, $:그것을 사용하기 위해 명명 된 정의에 갇혀 있어야합니다.


편집 : 24 문자?

몇 년 후, 나는 두 글자가 더 짧은 해결책을 발견했습니다.

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

그래도 속도가 훨씬 느립니다 3 ack 8. 내 컴퓨터에서 1 분 이상이 걸립니다. (1) 나는 배를 사용하기 때문입니다 /반복 대신 J 아마 평소보다 일을 기억해야하므로, (2)이 때, 0&<~수행과 같은 계산 (0<[), 실제로 실행 도착 n+1시간을 재귀 단계를 복용하기 전에 호출 m ack n-가 0&<발생 dem 등원이므로 계산을 망치지 않지만 n빨리 커지고 ack재귀 적입니다.

이전 코드 3 ack 10가 15 초 이내에 발견 될 수있는 컴퓨터이기 때문에 더 강력한 머신이 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

자바 스크립트 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

자바 스크립트 (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

코크, 40

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

이것은 유형의 함수입니다 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

수학, 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 배 이상 빠르다는 말씀이신가요?
Optimizer

@Optimizer 적어도 재귀에 관해서는 ... 사용할 정의를 매번 알아 내야 If하고 함수가되는 것이 더 느리다 면 부분을 추측 합니다.
Martin Ender

1
메모를 사용하면 0.07 초가 걸립니다. 즉 m_~a~n_:=m~a~n=...
마크 아들러

@MarkAdler Mathematica에서 메모를하는 정말 좋은 방법입니다!
Martin Ender

2

람다가있는 자바 스크립트, 34

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

간단한 대답은 더 짧은 것을 만들 수 없습니다.


2

Haskell, 48 44 문자 (목록은 36 자)

다른 Haskell 솔루션만큼 짧지는 않지만 Ackermann 기능을 무한 목록으로 표현하기 때문에 주목할 만합니다. 결과는 [m, n] 위치 에 값 A (m, n)을 보유 하도록 무한리스트 (무한리스트 ) 입니다.

무한 목록 자체 :

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

기능으로 (사양을 준수하기 위해) :

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

Ackermann 함수의 일반적인 / 일반적인 경우는 왼쪽의 값을 위의 행에서 색인으로 사용한다는 것을 관찰하여 공식을 도출했습니다. 이 재귀의 기본 경우 (즉, 행의 가장 왼쪽 열, 즉 A (m, 0) )는 위 행에서 두 번째로 가장 왼쪽에있는 값을 사용하는 것입니다. 대 기부 경우 재귀가있다 = N + 1 A (0, n)의 경우, 즉 첫 번째 행이다 [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

2

작은 리스프 , 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))))))

이것은 AAckermann 함수를 계산 하는 함수 를 정의 합니다. 형식화 :

(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(정의) 및 q(따옴표) 및 i(if))와 하나의 내장 함수 ( s– 빼기)를 사용하고 있습니다.

i 조건이 숫자> 0 일 때 (그리고 그렇지 않은 경우) 실제 부분을 실행하므로 여기서 명시 적으로 비교할 필요가 없습니다.

s유일한 연산이 가능하며, 우리는 그것을 사용 n-1/ m-1뿐만 아니라 등 (s n (s 0 1))을위한 n+1.

작은 리스프는 꼬리 재귀 최적화를 사용하지만 A결과 에 대한 외부 호출 에만 도움이 A(m, n-1)되고 매개 변수에 사용되는 호출에는 도움이 되지 않습니다 .

JVM의 Ceylon에서 작은 lisp 구현 을 사용하면 작동 (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

이동, 260 243 240 122 바이트

나는 그 질문에 anon funcs가 허용되는 것을 보지 못했다.

경쟁력이 없지만 나는이 언어를 배우고 있으며 그것을 테스트하고 싶었습니다.

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하고 두 숫자을 공급 m하고 n. m> 4 또는 n> 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

@EMBLEM 고마워, Go 줄을 쓴 지 너무 오래되었지만, 다른 Go-golfers가 있다는 것을 알게되어 기쁩니다. : D
cat

1

하스켈 : 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

당신은 또한 네 번째 줄에 괄호를 놓치고 있습니다
자랑스런 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,9is) \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 분 이상 걸리므로 마지막 쌍에 실패합니다 .

값이 높을수록 값 m을 늘려야합니다 recursionlimit.


나는 그것을 65 바이트로 더 짧게 얻었지만 질문의 요구 사항을 충족시키지 못할 것입니다. 포함하지 않는 {}이 TIO에 시간 제한과 마지막 두 항목의 데모를하지 않습니다.

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 vs 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 바이트를 저장합니다. 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]])}

설명

이것은 문제 설명에 주어진 알고리즘을 매우 간단하게 번역 한 것입니다.

  • 입력은 람다에 대한 인수로 사용됩니다. 두 가지 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 2016 년

골프 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

Mouse-2002 , 99 83 바이트

$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+;;]]]@

0

자바, 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)몇 초에서 무한 메모리 스택 공간 감안할 때의 임의의 조합을 산출 할 수 bB한 결과가 2 이하로 2147483647 -1.


나는 그것이 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)));}
오래

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하여 저장할 수 있습니다 < 1.

의 기본 설정으로 ceylon run, 그것까지 작동합니다 A(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를 자바 스크립트로 컴파일의 결과를 실행) 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 분이 걸립니다. (나는 원래 내가 가지고있는 튜플 대신 게으른 iterables를 사용하는 버전을 가지고 있었는데, 같은 크기로 훨씬 느 렸습니다.)

조금 더 빠른 (21 초 A(3,12)) (그러나 1 바이트 더 큼 )은 s.push대신을 사용하는 버전 s.addAll이지만 여러 개의 숫자를 추가하려면 각각 단일 정수가 필요하기 때문에 여러 번 호출해야했습니다. ArrayList 대신 LinkedList를 사용하면 속도가 훨씬 느려집니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.