Evaluate the nth hyperoperation
APL, 62
{1=3⌷⍵:2⌷+\⍵⋄0=2⌷⍵:(⍵[3]⌊3)⌷⍵[1],0,1⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1}⎕
{...}⎕
: Takes evaluated input (space-separated numbers evaluates to a numerical array) and apply function to it.
1=3⌷⍵:
: If n equals 1...
2⌷+\⍵
: Return sum of first 2 elements (x+y)...
⋄0=2⌷⍵:
: Else if y equals 0...
(⍵[3]⌊3)⌷⍵[1],0,1
: Create numerical array [x,0,1] and return index min(n,3)
...
⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1
: Else return ∇(x,∇(x,y-1,n),n-1). (∇ is self-reference)
I have got a "hyper-raiser" operator, which takes a function and return next hyperoperation
{⍺⍺/⊃⍴/⌽⍵}
For example, +{⍺⍺/⊃⍴/⌽⍵}
would be the multiplication function and +{⍺⍺/⊃⍴/⌽⍵}5 3
outputs 15.
But can't get it to recurse. Maybe someone else can do it.
Ruby, slow, 86 84 83 characters
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, fast, 96 94 93 characters
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)
The first version is way too slow with the last test case, so I added a version that uses multiplication as the base case instead of addition. The first version takes ages to calculate 3 3 4
; the second one is instanteneous (in the native IRB console; the web version is a bit slower).
Several beauties of Ruby show up here:
Almost every statement is an expression in ruby. Thus, you can stuff semicolons inside the ternary operator, provided you've got enough parentheses lying around. Coffeescript borrowed that one. It also borrowed Ruby's "no parens needed" call syntax.
Implicit returns: this is a cool feature, and follows from the previous. Indeed, starting the last line of a function with return
is considered lame, even when not golfing.
Numbers are objects in ruby (even null
is an object). In ruby, integers have the method times
, which executes the block passed to it several times. This is just one of Ruby's many iterator methods. Here, the upto
method lets us save two more characters over what times
lets us.
unary *
is the splat operator here. It turns an array into an argument list. Just like Javascript's Function#apply
, but it's shorter and better.
unary &
turns a procedure into a block. While :to_i
is a symbol, it converts into a procedure pretty well. Namely, it turns into a procedure that calls to_i
on its argument and returns the result. More information on Stack Overflow.
It would be possible to get it even faster by using n=3
as the base case, but I'm afraid it is not needed. It would only cost 11 characters, though, thanks to another beauty of ruby: the exponentiation operator **
. Python has this operator, but it's not the first one (as @aka.nice noted - thanks -, Fortran already had this operator).
online ruby interpreter available here: http://repl.it/Ikj/1
APL (Dyalog Unicode), 31 23 22 bytes (SBCS)
Saved 6 bytes thanks to Bubbler
{×a←⍺-1:a∇⍣⍵×⍺-2⋄⍵+⍺⍺}
Try it online!
Can be used as n (x f) y
.
{
×a←⍺-1: ⍝ Check if n is greater than 1
a←⍺-1 ⍝ Assign n - 1 to a variable a to reuse later
× ⍝ Sign of a (0 if addition, 1 otherwise)
a∇⍣⍵×⍺-2 ⍝ Apply the (n-1)th hyperoperation y times to x
×⍺-2 ⍝ Sign of n-2 (the identity for the nth hyperoperation
⍣ ⍝ Power operator, apply
∇ ⍝ the derived function (f x)
⍵ ⍝ y times
×⍺-2 ⍝ to the identity
a ⍝ With n-1 as the new n
⋄
⍵ + ⍺⍺ ⍝ n is 1 (addition)
}
```