我尝试用函数式编程语言中的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
有人可以协助我获得这种算法的纯功能方法吗?
答案 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)
}