阿克曼在斯威夫特中的作用

时间:2015-12-24 17:20:05

标签: ios swift math recursion

尝试做ack(4,1)但Swift也遇到错误,抱怨Objective-c类型。但Objc在33秒内找到答案65533没有问题。

如果你经营一个游乐场,它将需要永远。

这是错误 enter image description here

http://rosettacode.org/wiki/Ackermann_function#Swift

seeds.rb

2 个答案:

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

它适用于我在操场上。