Đánh giá siêu phẫu thuật thứ n


12

Tôi nhận ra rằng đây là một chút toán học, nhưng - ở đây đi.

Trong toán học, chuỗi siêu hoạt động là một chuỗi vô hạn của các phép toán số học (được gọi là siêu hoạt động) bắt đầu bằng phép toán đơn vị kế, sau đó tiếp tục với các phép toán nhị phân cộng, nhân và lũy thừa, sau đó chuỗi tiếp tục với các phép toán nhị phân tiếp tục mở rộng lũy thừa, sử dụng kết hợp đúng.

Mục tiêu của bạn là viết một chương trình lấy ba số nguyên x, y và n làm đầu vào và đưa ra kết quả của siêu hoạt động thứ n trên x và y.

Ví dụ

1 1 1 đầu ra 2

2 4 4 đầu ra 65536

3 3 4 đầu ra 7625597484987

  • Chương trình phải được viết bằng đoạn mã ngắn nhất.
  • Bạn có thể lấy đầu vào từ STDINhoặc từ một tập tin.
  • Chức năng thư viện không được phép.
  • Ràng buộc đầu vào: n sẽ là ≥ 1.

http://en.wikipedia.org/wiki/Tetration có một lời giải thích tốt trong trường hợp bạn không thể quấn đầu xung quanh vấn đề này.


n=1gì Nếu nó x+yhoặc x+1, 1 1 1nên quay lại2
John Dvorak

Tôi biết tôi đã phạm sai lầm ở đâu đó :) đã sửa, thx.
Soham Chowdhury

1
Tôi đã viết cho tôi một mã giả, sau đó tôi nhận ra rằng đó thực sự là mã Ruby hợp lệ (gần như :-()
John Dvorak

1
Không, n> = 1 chỉ.
Soham Chowdhury

Câu trả lời:


4

Ruby, chậm, 86 84 83 ký tự

def f x,y,n
n>1?(c=x;2.upto(y){c=f(x,c,n-1)};c):x+y
end
p f *gets.split.map(&:to_i)

Ruby, nhanh, 96 94 93 ký tự

def f x,y,n
n>1?(n>2?(c=x;2.upto(y){c=f(x,c,n-1)};c):x*y):x+y
end
p f *gets.split.map(&:to_i)

Phiên bản đầu tiên là cách quá chậm với trường hợp thử nghiệm cuối cùng, vì vậy tôi đã thêm một phiên bản sử dụng phép nhân như trường hợp cơ sở thay vì bổ sung. Phiên bản đầu tiên mất nhiều năm để tính toán 3 3 4; cái thứ hai là tức thời (trong bảng điều khiển IRB gốc; phiên bản web chậm hơn một chút).

Một số người đẹp của Ruby xuất hiện ở đây:

Hầu như mọi tuyên bố là một biểu hiện trong ruby. Do đó, bạn có thể nhét dấu chấm phẩy bên trong toán tử ternary, miễn là bạn có đủ dấu ngoặc đơn nằm xung quanh. Coffeescript mượn cái đó. Nó cũng mượn cú pháp cuộc gọi "không cần parens" của Ruby.

Trả về ngầm định: đây là một tính năng thú vị và được làm theo từ trước đó. Thật vậy, bắt đầu dòng cuối cùng của một chức năng returnđược coi là khập khiễng, ngay cả khi không chơi gôn.

Số là các đối tượng trong ruby ​​(thậm chí nulllà một đối tượng). Trong ruby, số nguyên có phương thức times, thực thi khối được truyền cho nó nhiều lần. Đây chỉ là một trong nhiều phương pháp lặp của Ruby. Ở đây, uptophương thức cho phép chúng ta lưu thêm hai ký tự so với những gì timescho phép chúng ta.

unary *là toán tử splat ở đây. Nó biến một mảng thành một danh sách đối số. Giống như Javascript Function#apply, nhưng nó ngắn hơn và tốt hơn.

unary &biến một thủ tục thành một khối. Trong khi :to_ilà một biểu tượng, nó chuyển đổi thành một thủ tục khá tốt. Cụ thể, nó biến thành một thủ tục gọi to_iđối số của nó và trả về kết quả. Thêm thông tin về Stack Overflow.

Có thể lấy nó nhanh hơn bằng cách sử dụng n=3làm trường hợp cơ bản, nhưng tôi sợ nó không cần thiết. Tuy nhiên, nó chỉ có giá 11 ký tự, nhờ vào một vẻ đẹp khác của ruby: toán tử lũy thừa **. Python có toán tử này, nhưng nó không phải là toán tử đầu tiên (như @ aka.nice lưu ý - cảm ơn -, Fortran đã có toán tử này).

thông dịch viên ruby ​​trực tuyến có sẵn ở đây: http://repl.it/Ikj/1


Đẹp, nhưng tôi vẫn đang chờ đầu ra từ 3 3 4:) nó rất chậm.
Soham Chowdhury

@SohamChowdhury trường hợp cơ sở là bổ sung. Với một trường hợp cơ bản của phép nhân, nó cũng sẽ rất chậm (và lâu hơn). Tôi khuyên bạn nên thử nghiệm với lũy thừa thay thế ;-)
John Dvorak

có thể tiết kiệm thời gian để sử dụng ghi nhớ, nhưng điều đó sẽ tốn một số byte (khá ít)
John Dvorak

Thêm phiên bản khác sau đó :)
Soham Chowdhury

1
toán tử ** đã tồn tại trong FORTRAN trong những năm 50 và ALGOL sẽ có ít hơn 1 ký tự với mũi tên lên
aka.nice

6

APL, 62

{1=3⌷⍵:2⌷+\⍵⋄0=2⌷⍵:(⍵[3]⌊3)⌷⍵[1],0,1⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1}⎕

{...}⎕: Đưa đầu vào được đánh giá (các số được phân tách bằng dấu cách ước tính thành một mảng số) và áp dụng hàm cho nó.

1=3⌷⍵:: Nếu n bằng 1 ...
2⌷+\⍵: Trả về tổng của 2 phần tử đầu tiên (x + y) ...
⋄0=2⌷⍵:: Khác nếu y bằng 0 ...
(⍵[3]⌊3)⌷⍵[1],0,1: Tạo mảng số [x, 0,1] và chỉ mục trả về min(n,3)...
⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1: Khác trả về ∇ (x, (x, y-1, n), n-1). (Là tự tham khảo)


Tôi đã có một toán tử "hyper-raiser", có chức năng và trả lại lần phẫu thuật tiếp theo

{⍺⍺/⊃⍴/⌽⍵}

Ví dụ, +{⍺⍺/⊃⍴/⌽⍵}sẽ là hàm nhân và +{⍺⍺/⊃⍴/⌽⍵}5 3đầu ra 15.

Nhưng không thể có được nó để tái diễn. Có lẽ người khác có thể làm điều đó.


À, APL. Đánh bại Python để đơn giản bất cứ ngày nào. </ mỉa mai> Làm thế nào để tôi chạy cái này?
Soham Chowdhury

2

Con trăn, 83

(Dựa trên câu trả lời của flornquake )

def h(x,y,n):r=n>2;exec"r=h(x,r,n-1);"*y*(n>1);return(x+y,r)[n>1]
print h(*input())

Rất chậm cho kết quả lớn.

Đối với 2, 4, 4đầu ra là 65536.


"Rất chậm" là lý do giải pháp 86 ký tự của tôi bị coi là xấu.
John Dvorak

1
@JanDvorak: Tại sao bạn nghĩ nó bị coi là xấu? Soham Chowdhury chỉ nói rằng nó chậm và bạn nên thêm một phiên bản khác, không phải là bạn thay thế giải pháp của mình. (Nhưng có lẽ tôi đã hiểu nhầm điều đó.)
Phục hồi Monica

Bạn đúng; khôi phục phiên bản ngắn. Bây giờ tôi chỉ là một char lâu hơn bạn.
John Dvorak

@WolframH chính xác. Luôn luôn tốt đẹp để có phiên bản.
Soham Chowdhury

2

Con trăn, 96 92

def h(x,y,n):r=1;exec(n>2)*y*"r=h(x,r,n-1);";return(r,(x+y,x*y)[n>1])[n<3]
print h(*input())

Đầu vào: 3, 3, 4
Đầu ra:7625597484987

Rút ngắn bằng cách sử dụng một vài ý tưởng của @ WolframH .


2

Golf, chậm, 39 ký tự

 ~{\(.{3${[4$\2$4$.~}4$(*}{;;+}if])\;}.~

(liên kết trực tiếp)

Đây là thuật toán đệ quy tiêu chuẩn với trường hợp cơ bản là n = 1 (phép cộng) (tức là chậm). Giống như tôi đã sử dụng trong giải pháp Ruby của tôi

Đây là một phiên bản với các chú thích của tôi (chủ yếu là giữ chồng). Nó không bao gồm một tối ưu hóa mà tôi đã thêm sau:

~{            #read the input and do (x y n f)
 \(.{         #(x y f n-1); if(n-1)
  3${         #(x y f n-1 c)
   4$\2$4$.~  #(x y f n-1 x c n-1 f); call
  }3$(*       #y-1 times
  {\;}4*
 }{           #else
  ;;+         #return (x+y)
 }if
}.~           #once

~là toán tử eval. Trong trường hợp chuỗi, nó xử lý chuỗi như một chương trình GolfScript. May mắn thay, một danh sách các số nguyên được phân tách bằng dấu cách là một chương trình GolfScript hợp lệ để đẩy các số nguyên đó lên ngăn xếp. So với điều này, phiên bản trước của thói quen nhập liệu (được " "/{~}/phân chia theo khoảng trắng và eval từng) là khá khập khiễng. Trong trường hợp của hàm, nó gọi hàm. Khi đứng trước .(clone), nó gọi hàm với chính nó là đối số đầu tiên.

Golfscript dường như không thực sự phù hợp để thực hiện các thuật toán đệ quy. Nếu bạn muốn một thuật toán đệ quy không tối ưu hóa cuộc gọi đuôi, bạn cần tạo và hủy các khung ngăn xếp để bảo toàn các biến của mình. Trong hầu hết các ngôn ngữ, điều này được thực hiện tự động. Trong golfscript, bạn phải thực sự sao chép các biến (thực ra là ngăn xếp các mục) và hủy các mục ngăn xếp mà bạn không còn cần nữa. Golfscript không có khái niệm về khung stack. Tôi có nói GolfScript là ngôn ngữ dựa trên ngăn xếp không?

Yêu cầu đầu tiên là dễ hiểu. Bạn phải xác định các đối số bằng cách nào đó. Nó chỉ tốt nếu họ giữ vị trí ban đầu của họ là tốt. Yêu cầu thứ hai là không may, đặc biệt là vì giá trị trả về nằm trên đỉnh của ngăn xếp và golfs thiếu khả năng xóa bất kỳ phần tử ngăn xếp nào. Bạn có thể xoay ngăn xếp và loại bỏ phần tử hàng đầu mới, nhưng điều đó sẽ nhanh chóng tích tụ. \;Ổn. \;\;\;\;\;không phải. Bạn có thể thực hiện \;trong một vòng lặp ( {\;}9*; chi phí: 6 ký tự để loại bỏ tối đa 9 phần tử hoặc 7 ký tự để loại bỏ tối đa 99 phần tử), nhưng chúng ta có thể làm tốt hơn:

Golfscript có mảng hạng nhất. Nó cũng có cú pháp mảng [1 2 3 4]. Điều bất ngờ là điều đó []thực sự không phải là một phần của cú pháp. Chúng chỉ đơn thuần là hai toán tử: [đánh dấu vị trí hiện tại trên ngăn xếp và ]thu thập mọi phần tử cho đến khi tìm thấy dấu bắt đầu của mảng hoặc hết ngăn xếp và loại bỏ dấu. Bạn thậm chí có thể xé hai cái này ra và xem điều gì xảy ra. Chà, khá là thú vị:

Tôi đã nói golfscript không có khái niệm về khung stack? Tôi đã nói dối. Đây là một khung ngăn xếp : [. Bạn có thể loại bỏ tất cả cùng một lúc : ];. Nhưng nếu chúng ta muốn giữ giá trị trả về thì sao? Bạn có thể đóng khung ngăn xếp trên mục nhập chức năng (khi đó chúng ta có một phiên bản hơi bị xáo trộn - không phải là một khái niệm thú vị) hoặc chúng ta có thể đóng khung ngăn xếp và lấy phần tử cuối cùng của nó thay vì loại bỏ hoàn toàn: ]-1=hoặc chúng ta có thể hủy bỏ phần tử cuối cùng thay vào đó, và sau đó loại bỏ khung : ])\;. Chúng có cùng chiều dài, nhưng cái sau thì mát hơn một chút, vì vậy tôi đang sử dụng nó.

Vì vậy, thay vì 6 hoặc 7 ký tự để dọn dẹp, chúng ta có thể làm với 5. Tôi vẫn cảm thấy điều này có thể được đánh gôn nhiều hơn, nhưng này, chúng ta đã cứu một nhân vật.


"Gọi hàm với chính nó là đối số đầu tiên" - ý tưởng thú vị cho phép đệ quy
aditsu bỏ vì SE là EVIL

1

Smalltalk Squeak 4.x hương vị nhiều byte!

Tôi có thể triển khai một trong các hình thức đệ quy trong Integer trong 71 char

f:y n:n n=1or:[^(2to:y)inject:self into:[:x :i|self f:x n:n-1]].^self+y

Sau đó, đọc từ một tệp hoặc FileStream stdin sẽ khiến tôi mất một cánh tay ... Squeak rõ ràng không được thiết kế như một ngôn ngữ kịch bản. Vì vậy, tôi sẽ dành nhiều byte để tạo các tiện ích cho mục đích chung của riêng mình không liên quan đến vấn đề:

Thực hiện phương thức 21 char này trong Luồng (để bỏ qua các trình thu thập dữ liệu)

s self skipSeparators

Thực hiện phương thức 20 char này trong Hành vi (để đọc một thể hiện từ Luồng)

<s^self readFrom:s s

Sau đó, 28 ký tự trong Chuỗi (để tạo một tệp xử lý)

f^FileDirectory default/self

Sau đó, 59 ký tự trong FileDirectory (để tạo readStream)

r^FileStream concreteStream readOnlyFileNamed:self fullName

Sau đó, 33 ký tự trong BlockClences (để đánh giá nó n lần)

*n^(1to:n)collect:[:i|self value]

Sau đó, 63 ký tự trong Mảng (đánh giá đối số với người nhận và đối số được lấy từ Mảng)

`s^self first perform:s asSymbol withArguments:self allButFirst

sau đó giải quyết vấn đề bằng cách đánh giá đoạn trích 31 char này ở bất cứ đâu để đọc từ tệp có tên x

|s|s:='x'f r.[0class<s]*3`#f:n:

Ngay cả khi không tính các tiện ích, đó là 71 + 31 = 102 ký tự đã ...

Bây giờ, vì tôi chắc chắn sẽ mất codeGolf, tôi có một triển khai hài hước hơn trong Integer:

doesNotUnderstand:m
    (m selector allSatisfy:[:c|c=$+])or:[^super doesNotUnderstand:m].
    self class compile:
        m selector,'y y=0or:[^(2to:y)inject:self into:[:x :i|self'
        ,m selector allButLast,'x]].^'
        ,(Character digitValue:()asBit)
        ,(m selector size-2min:1)hex last.
    thisContext sender restart

Phương thức này sẽ định nghĩa (biên dịch) một thông điệp nhị phân được tạo bằng n + nếu nó không tồn tại (không được người nhận tin nhắn m) hiểu và sẽ khởi động lại thực thi khi bắt đầu bối cảnh của người gửi. Tôi chèn trở lại vận chuyển bổ sung và không gian cho dễ đọc.

Lưu ý rằng đó (m selector size-2min:1)hex lastlà một hình thức rút gọn của (m selector size>2)asBit printString.

Nếu không thể chứng minh siêu năng lực tà ác của Smalltalk, câu nói cuối cùng có thể được thay thế bằng cách ngắn hơn và đơn giản hơn

^m sendTo:self

Bây giờ triển khai tiện ích 28 ký tự trong Ký tự (để lặp lại n lần trong Chuỗi)

*n^String new:n withAll:self

Sau đó đánh giá biểu thức 43 ký tự này:

|i s|i:=0class.s:='x'f r.[i<s]*2`($+*(i<s))

Chúng tôi có thể tăng tốc với 10 ký tự nữa bằng cách triển khai trong Integer:

++y^self*y

và trong trường hợp này chúng tôi cũng có mã ngắn hơn vì chúng tôi có thể thay thế ^',(m selector size-2min:1)hex lastbằng^1'

Với mức giá cao như vậy, mã làm việc với số nguyên thứ hai = 0 :)


0

Groovy - 77

h={x,y,n->n<2?x+y:y<2?x:h(x,h(x,y-1,n),n-1)}
print h(args.collect{it as int})

Lưu ý: nó yêu cầu số lượng ngăn xếp (và thời gian) tục tĩu cho các đối số không nhỏ.


0

Hệ thống đại số máy tính AXIOM, byte 69

p(x,y,n)==(n<=1=>y+x^n;n=2=>y*x;n=3=>x^y;y<=0=>1;p(x,p(x,y-1,n),n-1))

kiểm tra:

(2) -> p(1,1,1)
   (2)  2
                                                 Type: Expression Integer
                                   Time: 0.05 (IN) + 0.03 (OT) = 0.08 sec
(3) -> p(2,4,4)
   (3)  65536
                                                 Type: Expression Integer
                                                              Time: 0 sec
(4) -> p(3,3,4)
   (4)  7625597484987
                                                 Type: Expression Integer
                                                              Time: 0 sec

Điều này sẽ loại bỏ một số đệ quy ... Có thể tôi trao đổi trong x và y trong một số trả lại ... có các giá trị thử nghiệm khác không?


0

APL (NARS), ký tự 61, byte 122

{(x y n)←⍵⋄n≤1:y+x*n⋄n=2:x×y⋄n=3:x*y⋄y≤0:1⋄∇x,(∇x(y-1)n),n-1}

kiểm tra:

  h←{(x y n)←⍵⋄n≤1:y+x*n⋄n=2:x×y⋄n=3:x*y⋄y≤0:1⋄∇x,(∇x(y-1)n),n-1}
  h 1 1 1
2
  h 2 4 4
65536
  h 3 4 4
∞
  h 3 3 4
7625597484987
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.