功能编程语言中的棒切割

时间:2014-11-15 00:31:31

标签: scala functional-programming memoization

我尝试用函数式编程语言中的memoization实现棒切割问题,同时试图遵循不变性,但我不知道如何能够这样做。切杆问题的算法是......

memoized-cut-rod(p, n)
let r[0..n] be a new array
for i = 0 to n
    r[i] = -infinity
return memoized-cut-rod-aux(p, n, r)

memoized-cut-rod-aux(p, n, r)
if r[n] >= 0
    return r[n]
if n == 0
    q = 0
else
    q = -infinity
    for i = 1 to n
        q = max(q, p[i] + memoized-cut-rod-aux(p, n - i, r))
    r[n] = q
return q

有人可以协助我获得这种算法的纯功能方法吗?

2 个答案:

答案 0 :(得分:0)

以下是自上而下算法到Scala的转换。记忆值是memoizedCutRod的本地值,因此它们对环境没有影响,即没有副作用。我换了几个名字。内部递归函数使用外部函数中的p,因为它没有改变,并且memo在递归函数的所有实例中共享。

我还将- infinity的使用更改为Option[Int],以便我们有一个明确的指标,表明该值尚未定义。我更喜欢使用"不可能"数字作为旗帜。

def memoizedCutRod(p: Array[Int], n: Int): Int = {
  val memo = new Array[Option[Int]](n+1)
  (0 to n).foreach(memo(_) = None)

  def memoizedCutRodAux(n: Int): Int = {
    if ( memo(n).isDefined ) memo(n).get
    else if ( n == 0 ) 0
    else {
      val q = (1 to n).map(i => p(i) + memoizedCutRodAux(n - i)).max
      memo(n) = Some(q)
      q
    }
  }

  memoizedCutRodAux(n)
}

答案 1 :(得分:0)

我尽力让它变得纯粹功能性。希望它满足

type P = Seq[Int]
type R = Seq[Option[Int]]
type M = (Int, R)
type N = (P, M)
type ~>[A, B] = PartialFunction[A, B]

val r: Int => R = Seq.fill(_)(None)

val exists: N ~> M = {
  case (_, (n, r)) => 
    r(n).fold(throw new MatchError)((_, r))
}

val zero: N ~> M = {
  case (_, (n, r)) if n == 0 =>
    (0, r.updated(n, Some(0)))
}

val other: (N => M, N) => M = {
  case (f, (p, (n, r))) =>
    ((0, r) /: (1 to n)) {
      case ((q, r), i) =>
        val (q1, r1) = f(p, (n - i, r))
        (math.max(q, q1), r1)
    }
}

val cut: N ~> M = exists orElse zero orElse {
  case n: N => other(cut, n)
}