尝试做ack(4,1)但Swift也遇到错误,抱怨Objective-c类型。但Objc在33秒内找到答案65533没有问题。
如果你经营一个游乐场,它将需要永远。
http://rosettacode.org/wiki/Ackermann_function#Swift
seeds.rb
答案 0 :(得分:3)
嗯,这里有几个问题。
一个是你的语法。您需要在致电n
时标记ackerman
参数,或将ackerman
声明更改为不需要标签:
func ackerman(m:Int, _ n:Int) -> Int {
if m == 0 {
return n+1
} else if n == 0 {
return ackerman(m-1, 1)
} else {
return ackerman(m-1, ackerman(m, n-1))
}
}
另一个问题是计算ackerman(4, 1)
需要65536级别的递归。如果我在没有标志编译的命令行程序中尝试这个,我会在37秒后得到一个SIGSEGV,可能是由于堆栈溢出。
但是,如果我使用优化进行编译,我会在9秒内得到正确的答案。据推测,使用优化进行编译可以减小每个堆栈帧的大小,或者启用尾递归(这会减少分配的堆栈帧数),或者两者兼而有之。
:; cat ackerman.swift
func ackerman(m:Int, _ n:Int) -> Int {
if m == 0 {
return n+1
} else if n == 0 {
return ackerman(m-1, 1)
} else {
return ackerman(m-1, ackerman(m, n-1))
}
}
print(ackerman(4, 1))
:; swiftc -O -o ackerman ackerman.swift && time ./ackerman
65533
real 0m9.544s
user 0m8.481s
sys 0m0.508s
如果我改变程序使用“溢出运算符”(允许算术溢出,不像溢出时调用fatalError
的普通运算符),我可以将它降低到8秒:
:; cat ackerman.swift
func ackerman(m:Int, _ n:Int) -> Int {
if m == 0 {
return n &+ 1
} else if n == 0 {
return ackerman(m &- 1, 1)
} else {
return ackerman(m &- 1, ackerman(m, n &- 1))
}
}
print(ackerman(4, 1))
:; swiftc -O -o ackerman ackerman.swift && time ./ackerman
65533
real 0m8.276s
user 0m7.189s
sys 0m0.501s
这是在Mac Pro(2013年末)3.5 GHz 6核Intel Xeon E5上。
答案 1 :(得分:0)
您使用的是Swift 2吗?在这种情况下试试这个:
func ackerman(m:Int, n:Int) -> Int {
if m == 0 {
return n+1
} else if n == 0 {
return ackerman(m-1, n: 1)
} else {
return ackerman(m-1, n: ackerman(m, n: n-1))
}
}
ackerman(3, n: 1)
它适用于我在操场上。