评估第n个超手术


12

我的确意识到这有点数学,但是-来了。

在数学中,超运算序列是无限的算术运算序列(称为超运算),从后继的一元运算开始,然后以加法,乘法和乘幂运算的二进制运算继续,此后,该序列继续进行进一步的二进制运算,其范围超出使用右联想进行求幂。

您的目标是编写一个程序,该程序将三个整数x,y和n作为输入,并输出x和y上第n个超级运算的结果。

例如

1 1 1 输出2

2 4 4 输出65536

3 3 4 输出7625597484987

  • 该程序必须用最短的代码编写。
  • 您可以STDIN从文件或从文件中获取输入。
  • 不允许使用库函数。
  • 输入约束:n将≥1。

http://en.wikipedia.org/wiki/Tetration提供了很好的解释,以防您无法解决这个问题。


什么n=1啊 如果是x+yx+11 1 1则应返回2
John Dvorak

我知道我在某个地方犯了错误:)已修复,谢谢。
Soham Chowdhury 2013年

1
我给我写了一个伪代码,然后我意识到它实际上是一个有效的Ruby代码(几乎是:
John Dvorak 2013年

1
不,仅n> = 1。
Soham Chowdhury 2013年

Answers:


4

露比慢点 86 84 83个字符

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)

露比快 96 94 93个字符

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)

第一个版本是这样太慢了与上次测试的情况下,所以我加了一个版本,使用倍增的基本情况,而不是加法。第一个版本需要时间来计算3 3 4; 第二个是瞬时的(在本机IRB控制台中;网络版本要慢一些)。

Ruby的一些优点出现在这里:

几乎每个语句都是用红宝石表达的。因此,只要周围有足够的括号,就可以在三元运算符中填充分号。Coffeescript借用了那个。它还借用了Ruby的“不需要parens”调用语法。

隐式返回:这是一个很酷的功能,它是从以前开始的。确实,return即使没有打高尔夫球,也要从功能的最后一行开始算是la脚。

数字是红宝石中的对象(甚至null是对象)。在ruby中,整数具有method times,该方法执行多次传递给它的块。这只是Ruby的许多迭代器方法之一。在这里,该upto方法使我们可以再保存两个字符times

一元*是splat运算符。它将数组变成参数列表。就像Javascript一样Function#apply,但是它更短,更好。

一元&将一个过程变成一个块。虽然:to_i是一个符号,但它可以很好地转换为过程。即,它将变成一个过程,该过程调用to_i其参数并返回结果。有关堆栈溢出的更多信息。

通过将其n=3作为基本案例,可以更快地获得它,但恐怕不需要它。不过,由于红宝石的另一个优点:取幂运算符,它仅花费11个字符**。Python具有此运算符,但它不是第一个(如@ aka.nice所指出的-谢谢-,Fortran已经具有此运算符)。

可在此处获得在线红宝石解释器:http : //repl.it/Ikj/1


很好,但是我仍在等待3 3 4:) 的输出,这非常慢。
Soham Chowdhury

@SohamChowdhury基本案例是加法。使用乘法的基本情况,它也将非常慢(并且更长)。我建议改为使用幂运算进行测试;-)
John Dvorak

可以节省使用备忘录的时间,但是会花费一些字节(不少)
John Dvorak

然后添加另一个版本:)
Soham Chowdhury 2013年

1
运算符**已在50年代的FORTRAN中存在,并且ALGOL的向上箭头会少1个字符
aka.nice 2013年

6

APL,62

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

{...}⎕:获取求值输入(以空格分隔的数字求值到数字数组),然后对其应用函数。

1=3⌷⍵::如果n等于1 ...
2⌷+\⍵:返回前2个元素的和(x + y)...
⋄0=2⌷⍵::否则如果y等于0 ...
(⍵[3]⌊3)⌷⍵[1],0,1:创建数值数组[x,0,1]并返回索引min(n,3)...
⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1:否则返回∇(x,∇(x,y-1,n),n-1)。(∇是自我参照)


我有一个“ hyper-raiser”运算符,它需要一个函数并返回下一个超操作

{⍺⍺/⊃⍴/⌽⍵}

例如,+{⍺⍺/⊃⍴/⌽⍵}将是乘法函数并+{⍺⍺/⊃⍴/⌽⍵}5 3输出15。

但是无法递归。也许别人可以做到。


啊,APL。每天都为简化而击败Python。</ sarcasm>我该如何运行?
Soham Chowdhury,2013年

2

Python,83岁

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

对于大型结果,非常慢。

对于2, 4, 4输出是65536


“非常慢”是我的86个字符的解决方案被认为不好的原因。
John Dvorak

1
@JanDvorak:您为什么认为它不好?Soham Chowdhury只是说它很慢,您应该添加另一个版本,而不是替换解决方案。(但也许我误会了。)
恢复莫妮卡

你是对的; 恢复了简短版本。现在我只是一个比你长的字符。
John Dvorak

完全是@WolframH。总是很高兴有版本。
Soham Chowdhury

2

蟒蛇,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())

输入:3, 3, 4
输出:7625597484987

使用@WolframH的一些想法来缩短。


2

Golfscript,慢,39个字符

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

(实时链接)

这是标准的递归算法,基本情况为n = 1(加法)(即慢)。我在Ruby解决方案中使用的相同

这是带有我的注释的版本(主要是堆栈保存)。它不包括我稍后添加的一项优化:

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

~是eval运算符。对于字符串,它将字符串视为GolfScript程序。幸运的是,用空格分隔的整数列表是有效的GolfScript程序,该程序将这些整数压入堆栈。与此相比,我以前的输入例程版本(" "/{~}/,分别由空格和eval分隔)非常me脚。如果是函数,它将调用该函数。当以.(clone)开头时,它以自身作为第一个参数调用函数。

Golfscript似乎并不完全适合于创建递归算法。如果您想要一个不能优化尾调用的递归算法,则需要创建和销毁堆栈框架以保留变量。在大多数语言中,这是自动完成的。在golfscript中,您实际上必须克隆变量(实际上是堆栈条目),并销毁不再需要的堆栈条目。Golfscript没有堆栈框架的概念。我是否说过GolfScript是基于堆栈的语言?

第一个要求是可以理解的。您必须以某种方式指定参数。如果他们也保持原来的位置,那就太好了。第二个要求是不幸的,特别是因为返回值在堆栈的顶部,并且golfscript缺少仅删除任何堆栈元素的能力。您可以旋转堆栈并丢弃新的顶部元素,但是很快就会建立起来。\;很好 \;\;\;\;\;不是。您可以\;循环执行({\;}9*;成本:6个字符最多可丢弃9个元素,或7个字符最多可丢弃99个元素),但我们可以做得更好:

Golfscript具有一流的数组。它还具有数组文字语法[1 2 3 4]。什么是意想不到的是,[]实际上不是语法的一部分。它们只是两个运算符:[标记堆栈上的当前位置,]收集每个元素,直到找到数组开始标记或堆栈用完,然后丢弃该标记。您甚至可以将这两部分分开,看看会发生什么。好吧,很有趣的事情:

我是否说golfscript没有堆栈框架的概念?我撒了谎。这是一个堆栈框架:[。您可以一次丢弃所有内容:];。但是,如果我们想保留返回值怎么办?您可以关闭函数入口上的堆栈框架(然后我们有一个稍微混乱的传递数组版本-一个有趣的概念),或者我们可以关闭堆栈框架并获取其最后一个元素,而不是完全丢弃它:]-1=或者可以取消取消约束最后一个元素,然后丢弃框架:])\;。它们的长度相同,但是后者稍凉一些,所以我正在使用它。

因此,我们可以用5代替6或7个字符进行清理。我仍然觉得可以打更多的球,但是,嘿,我们已经保存了一个字符。


“调用函数本身作为第一个参数” –递归的有趣想法
因为SE是EVIL,

1

Smalltalk Squeak 4.x风味很多字节!

我可以在71 char中实现Integer中的一种递归形式

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

然后从文件或FileStream stdin中读取将花费我一臂之力...显然,Squeak并非设计为脚本语言。因此,我将花费很多字节来创建自己的与该问题无关的通用实用程序:

在Stream中实现此21 char方法(以跳过分隔符)

s self skipSeparators

在行为中实现此20 char方法(以从Stream读取实例)

<s^self readFrom:s s

然后在String中输入28个字符(以创建文件句柄)

f^FileDirectory default/self

然后在FileDirectory中添加59个字符(用于创建readStream)

r^FileStream concreteStream readOnlyFileNamed:self fullName

然后在BlockClosure中将33个字符(进行n次评估)

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

然后在数组中添加63个字符(用接收者和从数组中获取的参数评估参数)

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

然后通过评估此31个char片段的位置以从名为x的文件中读取来解决问题

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

即使不计算实用程序,也已经是71 + 31 = 102个字符...

现在,由于我肯定会丢失codeGolf,因此我在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

如果该方法不存在(消息m的接收者无法理解),则该方法将定义(编译)由n +组成的二进制消息,并将在发送者上下文的开头重新开始执行。我插入了附加的回车符和空格以提高可读性。

请注意,这(m selector size-2min:1)hex last是的缩写形式(m selector size>2)asBit printString

如果不是要证明Smalltalk邪恶的超级大国,可以用更短和更简单的语句代替最后一个语句

^m sendTo:self

现在在Character中实现28个字符的实用程序(在String中重复n次)

*n^String new:n withAll:self

然后评估此43个字符的表达式:

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

通过在Integer中实现,我们可以再增加10个字符:

++y^self*y

在这种情况下,我们的代码也较短,因为我们可以^',(m selector size-2min:1)hex last^1'

对于这么高的价格,代码使用第二个整数= 0 :)



0

AXIOM计算机代数系统,字节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))

测试:

(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

这将消除一些递归...可能我会在某些回报中交换x和y ...还有其他测试值吗?


0

APL(NARS),字符61,字节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}

测试:

  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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.