Hàm Ackermann


35

Hàm Ackermann đáng chú ý là một trong những ví dụ đơn giản nhất về hàm tổng, tính toán không phải là đệ quy nguyên thủy.

Chúng tôi sẽ sử dụng định nghĩa A(m,n)lấy hai số nguyên không âm trong đó

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

Bạn có thể thực hiện

  • một hàm được đặt tên hoặc ẩn danh lấy hai số nguyên làm đầu vào, trả về một số nguyên hoặc
  • một chương trình lấy hai số nguyên được phân tách bằng dấu cách hoặc dòng mới trên STDIN, in kết quả thành STDOUT.

Bạn không được sử dụng chức năng Ackermann hoặc chức năng hạ âm từ thư viện, nếu có, nhưng bạn có thể sử dụng bất kỳ chức năng nào khác từ bất kỳ thư viện nào khác. Cấp số nhân thường xuyên được cho phép.

Hàm của bạn phải có thể tìm giá trị của A(m,n)m ≤ 3 và n ≤ 10 trong chưa đầy một phút. Nó ít nhất phải chấm dứt về mặt lý thuyết trên bất kỳ đầu vào nào khác: không gian ngăn xếp vô hạn, loại Bigint nguyên gốc và một khoảng thời gian dài tùy ý, nó sẽ trả về câu trả lời. Chỉnh sửa: Nếu ngôn ngữ của bạn có độ sâu đệ quy mặc định quá hạn chế, bạn có thể cấu hình lại mà không mất chi phí ký tự.

Bài nộp với số lượng nhân vật ngắn nhất sẽ thắng.

Dưới đây là một số giá trị, để kiểm tra câu trả lời của bạn:

  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
Làm thế nào có điều này không được hỏi trước ??
Sở thích của Calvin

9
Tôi nghĩ sẽ vui hơn khi tạo mã nhanh nhất
Sp3000

22
Hạ cấp vì không có thách thức ở đây. Câu trả lời rõ ràng - chỉ cần ngây thơ thực hiện chức năng chính xác theo định nghĩa của nó - luôn luôn là câu trả lời tốt nhất. Vì vậy, câu hỏi chỉ là "Ngôn ngữ nào có số lượng ký tự ít nhất trong biểu thức rõ ràng của chức năng Ackermann?" Người chiến thắng thực sự là ngôn ngữ lập trình, không phải là người đã viết chương trình rõ ràng trong đó.
David Richerby

1
Điều gì xảy ra nếu giới hạn đệ quy ngôn ngữ của tôi quá thấp để tính toán A(3,8)và ở trên một cách ngây thơ như những người khác đã làm? Tôi có phải đưa ra giải pháp không đệ quy không, hoặc tôi cũng có thể chỉ "giả định không gian ngăn xếp vô hạn" trong những trường hợp này? Tôi khá chắc chắn, nó sẽ chấm dứt trong vòng một phút.
Martin Ender

5
@DavidR Richby "Câu trả lời rõ ràng [...] luôn luôn là câu trả lời hay nhất." Điều này không đúng với tất cả các ngôn ngữ. Tôi cảm thấy hơi bẩn khi chỉ có một ví dụ bằng ngôn ngữ nhà của mình, nhưng có nhiều cách để diễn đạt Ackermann và trong một số ngôn ngữ bạn có thể tiết kiệm bằng cách sử dụng thực tế đó. Đây là ý định của tôi cho thử thách.
thuật toán

Câu trả lời:


7

Bình thường , 19

DaGHR?atG?aGtHH1GhH

Xác định a, hoạt động như chức năng Ackermann. Lưu ý rằng điều này đòi hỏi độ sâu đệ quy cao hơn trình biên dịch pyth chính thức cho phép cho đến ngày hôm nay để tính toán a 3 10, vì vậy tôi đã tăng độ sâu đệ quy. Đây không phải là một sự thay đổi ngôn ngữ, chỉ là trình biên dịch.

Kiểm tra:

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

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

Giải trình:

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)

Về cơ bản, điều kiện đầu tiên là giá trị thật của Gviệc tái diễn hay trả lại H + 1. Nếu nó đang được đệ quy, đối số thứ nhất luôn là G-1 và nó dựa trên giá trị thật của Hviệc sử dụng a(G,H-1)làm đối số thứ hai hay sử dụng 1làm đối số thứ hai.


Trong Pyth hiện đại (tôi cho rằng điều này đã được thêm vào sau thử thách này) Tôi nghĩ bạn có thể ít nhiều thay đổi DaGHRsang Mathành g. (Có phải thứ tự lập luận để ?thay đổi không?)
Lynn

@Mauris Có, bạn có thể sử dụng Mthay thế và có, ?thứ tự đối số đã thay đổi. Bây giờ là điều kiện, đúng, sai. Đó là sự thật, điều kiện, sai.
isaacg

@Lynn Sự thật lịch sử Pyth Fun: Câu hỏi này thực sự ảnh hưởng đến isaacg để thay đổi (ít nhất) hai điều về Pyth: giới hạn đệ quythay đổi thànhM !
FryAmTheEggman

23

Haskell, 35

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

cái này định nghĩa hàm toán tử %.

điều này hoạt động bằng cách nhận thấy rằng m%n( achức năng ackerman) cho nonzero mđược (m-1)%áp dụng n+1lần nào 1. ví dụ, 3%2được định nghĩa như 2%(3%1)2%(2%(3%0)), và đây là2%(2%(2%1))


quá tệ Tôi không thể sử dụng 0%nthay n+1vì vì quyền ưu tiên
tự hào


wow, điều này đã sai quá lâu, và không ai, kể cả bản thân tôi, nhận thấy? làm tốt lắm. Vì vậy, có vẻ như tôi đã sao chép nhầm phiên bản đầu tiên của câu trả lời bị lỗi, có thể do nhầm lẫn hoặc vì tôi nghĩ rằng nó đã hoạt động.
tự hào

12

GolfScript (30)

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

Bản demo trực tuyến

Nếu không có 1>(trường hợp đặc biệt A(1, n)), sẽ mất 9 phút để tính toán A(3, 10)trên máy tính mà tôi đã kiểm tra. Với trường hợp đặc biệt đó, đủ nhanh để bản demo trực tuyến chỉ mất chưa đến 10 giây.

Lưu ý rằng đây không phải là một bản dịch ngây thơ của định nghĩa. Độ sâu đệ quy được giới hạn bởi m.

Mổ xẻ

{             # 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, bạn sẽ không cần 1>. Sau khi xóa (và thay đổi ifthành ?), tính toán 3 10 Amất 110 giây với trình thông dịch trực tuyến và sáu giây với trình thông dịch Java.
Dennis

7

Phép tính lambda nhị phân , 54 bit = 6,75 byte

Hexdump:

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

Nhị phân:

000101100000011100101101100010000000011100101111011010

Đây là λ m . mg . λ n . g ( n g 1)) (λ n . λ f . λ x . f ( n f x )), trong đó tất cả các số được biểu diễn dưới dạng số Church .


6

JavaScript, ES6, 41 34 byte

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

Chạy cái này trong Bảng điều khiển Firefox mới nhất và nó sẽ tạo ra một hàm gọi là fbạn có thể gọi với các giá trị khác nhau mnthích

f(3,2) // returns 29

HOẶC LÀ

thử mã dưới đây trong Firefox mới nhất

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>


Thử nghiệm điều này với 0,1 trong Chrome không cho kết quả.
Nzall

3
Xin vui lòng đọc, điều này chỉ hoạt động trong Firefox mới nhất do ES6
Trình tối ưu hóa

Wow ... chúng tôi có 4 giải pháp JS thực tế giống hệt nhau, tất cả đều ở mức 34 byte. Tôi chưa bao giờ thấy điều đó trước đây.
Sản xuất ETH

6

Trăn 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

(Tín dụng cho xnor!)

Dễ đọc hơn, nhưng có thêm 1 ký tự:

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

Không phải là tôi phải thiết lập sys.setrecursionlimit(10000)để có kết quả A(3,10). Chơi gôn thêm bằng cách lập chỉ mục logic không hoạt động do độ sâu đệ quy tăng trưởng đáng kể.


Tôi nhận được một lỗi cú pháp trên 1else. Chữ cái bắt đầu egây rắc rối cho trình phân tích cú pháp vì các số có thể được viết như thế nào 1e3.
xnor

Đã lưu một vài ký tự chuyển sang and/or:A=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n
xnor

@xnor: Cảm ơn vì tiền boa! Xem cuộc thảo luận này cho vấn đề phân tích cú pháp. Python 2.7.8 chấp nhận 1else, hầu hết các phiên bản khác không có.
Falko

Cảm ơn con trỏ về 1else; nó cho phép tôi vắt kiệt than ở đây và có lẽ ở những nơi khác. Nhưng darn là phiên bản cụ thể! Python 2.7.4 không cho phép nó. Bạn đang sử dụng phiên bản trực tuyến với 2.7.8 hay tôi sẽ phải tải xuống?
xnor

@xnor: Đây là một cài đặt ngoại tuyến. ideone.com , ví dụ, không phân tích cú pháp 1elselà tốt.
Falko

6

J - 26 char

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

Có một định nghĩa thay thế, nhiều chức năng hơn của 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))

Nó như vậy sẽ xảy ra rằng Iterrất dễ dàng để ghi trong J, vì J có một cách để đi qua trong m-1để Ackvà cũng để xác định giá trị ban đầu của Iterlà 1. Giải thích bằng cách nổ:

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

Điều này phụ thuộc vào cái mà J gọi là hình thức gerund của ^:bá đạo về cơ bản là một cách để có nhiều quyền kiểm soát hơn đối với tất cả các giới hạn theo kiểu ngầm (không có điểm).

Tại 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

Chúng ta cần xác định acktên để có thể đặt nó vào một cái bàn, bởi vì $:nó là một con quái vật xấu xí, xấu xí và đả kích bất cứ ai cố gắng hiểu nó. Nó là tự tham chiếu, trong đó self được định nghĩa là cụm động từ lớn nhất chứa nó. tablelà một trạng từ và vì vậy rất thích trở thành một phần của cụm động từ nếu bạn cho nó cơ hội, vì vậy bạn phải đặt $:một định nghĩa có tên để sử dụng nó.


Chỉnh sửa: 24 char?

Nhiều năm sau, tôi tìm thấy một giải pháp ngắn hơn hai ký tự.

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

Tuy nhiên, nó chậm hơn rất nhiều: 3 ack 8mất hơn một phút trên máy của tôi. Điều này là do (1) Tôi sử dụng một lần /thay vì lặp lại, vì vậy J có thể phải nhớ nhiều thứ hơn bình thường và (2) trong khi 0&<~thực hiện phép tính tương tự như (0<[), nó thực sự được thực hiện n+1lần trước khi thực hiện bước đệ quy khi gọi m ack n- 0&<xảy ra là idempotent, vì vậy nó không phá hỏng tính toán, nhưng ntrở nên nhanh chóng và ackcó tính đệ quy cao.

Tôi nghi ngờ rằng một cỗ máy mạnh hơn có thể đẩy mã mới trong vòng một phút, bởi vì đây là máy tính mà mã cũ có thể tìm thấy 3 ack 10trong vòng chưa đầy 15 giây.


5

C - 41 byte

Không có gì với nó - các giới hạn nhỏ có nghĩa là tất cả các giá trị cần thiết có thể được tính trong chưa đầy 1 giây bằng cách ngây thơ theo định nghĩa hàm.

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

Thực hiện:

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

Và một bài kiểm tra:

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

Đây là một chức năng của loại nat -> nat -> nat. Vì Coq chỉ cho phép xây dựng các chức năng tổng thể, nó cũng đóng vai trò là bằng chứng chính thức cho thấy sự tái phát của Ackermann là có cơ sở.

Bản giới thiệu:

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

Lưu ý: Coq 8.5, phát hành sau khi thử thách này, đổi tên nat_iterđể Nat.iter.


2

Vợt 67

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

2

Toán học, 46 byte

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

Mất khá nhiều chính xác một phút cho a[3,10]. Lưu ý rằng giới hạn đệ quy mặc định của Mathistica quá nhỏ so với a[3,8](ít nhất là trên máy của tôi), nhưng có thể khắc phục bằng cách định cấu hình

$RecursionLimit = Infinity

1
Ồ, vậy bạn có nói rằng JS nhanh hơn Mathicala hơn 25 lần không?
Trình tối ưu hóa

@Optimizer Ít nhất là khi nói đến đệ quy ... Tôi đoán một phần nếu nó phải tìm ra mỗi lần định nghĩa nào sẽ sử dụng, và Iflà một hàm thậm chí còn chậm hơn.
Martin Ender

1
Với việc ghi nhớ, phải mất 0,07 giây. Tức là m_~a~n_:=m~a~n=...
Mark Adler

@MarkAdler Đó là một cách thực sự hay để học thuộc về Mathematica!
Martin Ender

2

Javascript với lambdas, 34

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

Một câu trả lời chính xác, không thể làm bất cứ điều gì ngắn hơn.


2

Haskell, 48 44 ký tự (36 cho danh sách)

Mặc dù không ngắn như các giải pháp Haskell khác, nhưng điều này đáng chú ý vì nó thể hiện chức năng Ackermann như một danh sách vô hạn, mà tôi nghĩ là khá gọn gàng. Kết quả là một danh sách vô hạn (của danh sách vô hạn) sao cho tại vị trí [m, n] nó giữ giá trị A (m, n) .

Danh sách vô hạn chính nó:

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

Là một chức năng (để tuân thủ các đặc điểm kỹ thuật):

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

Công thức được rút ra bằng cách quan sát rằng trường hợp chung / chung cho hàm Ackermann là sử dụng giá trị ở bên trái làm chỉ số trong hàng ở trên. Trường hợp cơ sở cho đệ quy này (tức là cột ngoài cùng bên trái của một hàng, tức là A (m, 0) ) là sử dụng giá trị ngoài cùng thứ hai trong hàng trên. Trường hợp cơ sở cho đệ quy đó là trường hợp A (0, n) = n + 1 , tức là hàng đầu tiên là [1..].

Như vậy, chúng ta có được

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

Sau đó, chúng tôi chỉ cần thêm một mức lặp khác dựa trên mẫu đó và thực hiện một số trò tung hứng vô nghĩa .


Bạn có thể đặt bí danh iteratecho một tên chữ cái duy nhất tức lài=iterate;ack=i ...
tự hào

@proudhaskeller oh yeah, đã không nghĩ về điều đó. Cảm ơn! Mượn tên sử dụng của nhà điều hành của bạn là tốt.
FireFly

2

Tiny Lisp , 70 (không tham gia cuộc thi)

Điều này hết cạnh tranh, vì ngôn ngữ mới hơn câu hỏi và nó cũng không thành công để chạy (A 3 10)theo yêu cầu trong câu hỏi, do tràn ngăn xếp.

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

Điều này xác định một hàm Atính toán hàm Ackermann. Định dạng:

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

Chúng tôi đang sử dụng tất cả các macro dựng sẵn ( d(xác định) và q(trích dẫn) và i(nếu)) và một hàm dựng sẵn ( s- trừ) ở đây.

i thực hiện phần thực của nó khi điều kiện là một số> 0 (và nếu không là phần sai), vì vậy chúng ta không phải thực hiện một so sánh rõ ràng ở đây.

slà hoạt động số học duy nhất có sẵn, chúng tôi sử dụng nó cho n-1/ m-1, cũng như (s n (s 0 1))cho n+1.

Tiny lisp đang sử dụng tối ưu hóa đệ quy đuôi, nhưng điều này chỉ giúp cho Acuộc gọi bên ngoài trong kết quả, không phải cho A(m, n-1)cuộc gọi được sử dụng cho các tham số.

Với việc triển khai lisp nhỏ của tôi trong Ceylon trên JVM, nó hoạt động được (A 3 5) = 253, nhưng dường như nó bị hỏng khi cố gắng tính (A 2 125)trực tiếp (sẽ cho kết quả tương tự). Nếu tính toán điều đó sau đó (A 3 4) = 125, JVM dường như phải tối ưu hóa các hàm đủ để thực hiện một số lệnh gọi hàm trung gian trong trình thông dịch của tôi, cho phép độ sâu đệ quy nhiều hơn. Lạ thật.

Việc thực hiện tham chiếu được lên đến (A 3 5) = 253và cũng được (A 2 163) = 329, nhưng không thành công (A 2 164), và do đó thậm chí còn ít hơn (A 3 6) = (A 2 253).


đây có thể là tiết kiệm cạnh tranh cho khoảng trắng và dấu ngoặc đơn;)
mèo

2

Đi, 260 243 240 122 byte

Tôi không thấy rằng câu hỏi cho phép anon funcs.

Khác xa với cạnh tranh nhưng tôi đang học ngôn ngữ này và tôi muốn thử nghiệm nó.

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}

sử dụng nó như thế go run ack.govà sau đó cung cấp hai số, mn. nếu m> 4 hoặc n> 30, thời gian thực hiện có thể vượt quá nửa phút.

cho m=3 n=11:

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

chỉnh sửa : lưu tổng 17 byte bằng cách chuyển sang switchhơn if/elsevà rải rác-nhập khẩu


1
Bạn có thể làm tốt hơn nữa! Tuyên bố switch 0 {case m:r=n+1 case n:r=a(m-1,1) default:r=a(m-1,a(m,n-1))}của Go switchrất linh hoạt!
EMBLEM

@EMBLEM Cảm ơn, đã quá lâu kể từ khi tôi viết một dòng cờ vây, nhưng tôi rất vui khi thấy có những người chơi gôn khác về: D
con mèo

1

Haskell: 81 69 byte

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 mất khoảng 45 giây.


1
Đây là mã golf, vì vậy bạn nên cố gắng có mã ngắn nhất có thể. ví dụ: xóa các khoảng trắng không cần thiết và loại rõ ràng
tự hào

bạn cũng đang thiếu các parens trên dòng thứ tư
tự hào




1

R - 54 52

Tôi đã sử dụng điều này như một cái cớ để thử và tìm hiểu về R, vì vậy điều này có lẽ thực sự tồi tệ :)

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

Chạy ví dụ

> a(3,8)
[1] 2045

Tôi nhận được một ngăn xếp tràn cho bất cứ điều gì ngoài đó

T-SQL- 222

Tôi nghĩ rằng tôi cũng sẽ cố gắng để T-SQL làm điều đó. Đã sử dụng một phương thức khác vì đệ quy không tốt trong SQL. Bất cứ điều gì hơn 4.2 quả bom nó.

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

đối với trình gửi R của bạn, có vẻ như bạn không cần {}mặc dù không giúp giới hạn ngăn xếp ngăn xếp, vì R không có TCO ...
Giuseppe

@Giuseppe cảm ơn ... để bảo vệ tôi, sau đó tôi mới biết về nó :)
MickyT

1

Brainfuck , 90 byte

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

Hãy thử trực tuyến!

Giả sử thực hiện với kích thước ô tùy ý, với IO là số. -6 byte nếu bạn không phiền khi sử dụng các ô âm.

Kết thúc sau khoảng 30 giây cho 3,8 trong trình thông dịch được liên kết, miễn là bạn đánh dấu vào các cài đặt chính xác. Nhập các số được nhập vào trước \s, ví dụ 3,9\3\9.


1

Tcl , 67 byte

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

Hãy thử trực tuyến!


Tcl , 77 byte

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

Hãy thử trực tuyến!

Trong trình biên dịch trực tuyến, nó không chạy được do hết thời gian, nhưng trong trình thông dịch Tcl cục bộ, nó chạy tốt. Tôi đã lược tả từng lệnh gọi gốc Ađể xem hàm tính toán mất bao nhiêu thời gian cho mỗi {m,n}đối tượng được kiểm tra:

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

Nó thất bại cho cặp cuối cùng {m,n}={3,10}, vì nó mất ít hơn một phút.

Đối với các giá trị cao hơn m, sẽ cần thiết để tăng recursionlimitgiá trị.


Tôi thay đổi ngắn hơn tới 65 byte, nhưng nó sẽ không đáp ứng yêu cầu của câu hỏi "Hàm của bạn phải có thể tìm giá trị của A (m, n) cho m ≤ 3 và n ≤ 10 trong chưa đầy một phút." Không có{} nó sẽ hết thời gian trên TIO và không thực hiện bản demo của hai mục cuối.

Tcl , 65 byte

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

Hãy thử trực tuyến!


0

J: 50

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

Trả về trong một phần của giây trong 0 ... 3 so với 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: "0 phục vụ để làm cho A hoạt động trên từng phần tử, thay vì ngấu nghiến mảng bên trái và bên phải và tạo ra các lỗi độ dài. Nhưng không cần thiết cho ví dụ 9 = 2 A 3.



0

APL, 31

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

Khá đơn giản. Sử dụng ký tự once một lần để lưu một byte bằng cách đảo ngược các đối số. Lấy m làm đối số bên trái và n là đối số bên phải.

Dùng thửAPAP.org


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

Giải trình

Đây là một bản dịch khá đơn giản của thuật toán được đưa ra trong mô tả vấn đề.

  • Đầu vào được lấy làm đối số cho lambda. HaiInteger s dự kiến.
  • Để biết tốc độ và tránh các lỗi tràn chồng, các câu trả lời được ghi nhớ trong Hash h. Các ||=nhà điều hành được sử dụng để tính toán một giá trị mà không tính toán trước đây.

a[3,10] được tính trong ~ 0,1 giây trên máy của tôi.

Đây là một phiên bản chưa được chỉnh sửa

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]ném SystemStackError vào máy của tôi ...
Thiền vào

Golf nitpicks: Bạn có thể đổi m<1?(n+1):(n<1?a[m-1,1]:a[m-1,a[m,n-1]])thànhm<1?n+1:a[m-1,n<1?1:a[m,n-1]]
Nghệ thuật đơn giản đẹp vào


0

Java, 274 byte

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

Nó tính toán A(3,10)trong vài giây và được cung cấp bộ nhớ vô hạn và không gian ngăn xếp, nó có thể tính toán bất kỳ sự kết hợp nào bBmiễn là kết quả dưới 2 2147483647 -1.


Tôi biết đã được một lúc, nhưng bạn có thể chơi golf tới 185 byte :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 21/03/18

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

Đây là một thực hiện đơn giản. Định dạng:

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

Bí danh chỉ lưu một byte, nếu không có nó (bằng văn bản Integerthay vì I), chúng ta sẽ có được tới 86 byte. Hai byte khác có thể được lưu bằng cách thay thế == 0bằng< 1 hai lần.

Với các cài đặt mặc định của ceylon run, nó sẽ hoạt động lên đến A(3,12) = 32765(và A(4,0) = 13), nhưng A(3,13)(và do đó A(4,1)) cũng sẽ gây ra lỗi tràn ngăn xếp. ( A(3,12)mất khoảng 5 giây,A(3,11) khoảng 3 trên máy tính của tôi.)

Việc sử dụng ceylon run-js(nghĩa là chạy kết quả biên dịch sang JavaScript trên node.js) chậm hơn rất nhiều (cần 1 phút 19 giây A(3,10)) và đã phá vỡ A(3, 11)với một »Kích thước ngăn xếp cuộc gọi tối đa vượt quá« (sử dụng cài đặt mặc định) sau khi chạy 1 tối thiểu 30 giây.


Ceylon không có đệ quy, 228

Như một phần thưởng, đây là một phiên bản không đệ quy (dĩ nhiên, lâu hơn, nhưng miễn dịch với chồng tràn - có thể bị lỗi hết bộ nhớ tại một số điể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{return m;}}}}

Định dạng:

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

Nó khá chậm trên máy tính của tôi so với phiên bản đệ quy: A(3,11)mất 9,5 giây, A(3,12)mất 34 giây, A(3,13)mất 2:08 phút,A(3,14) mất 8:25 phút. (Ban đầu tôi có một phiên bản sử dụng các iterables lười biếng thay vì các bộ dữ liệu hiện có, thậm chí còn chậm hơn nhiều, với cùng kích thước).

Nhanh hơn một chút (21 giây cho A(3,12)) (nhưng cũng dài hơn một byte) là phiên bản sử dụng s.pushthay vì s.addAll, nhưng cần phải gọi nhiều lần để thêm nhiều số, vì mỗi số chỉ cần một Số nguyên. Sử dụng LinkedList thay vì ArrayList chậm hơn rất nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.