可以用尾递归形式编写卷积函数吗?

时间:2017-01-11 07:39:02

标签: recursion functional-programming dynamic-programming tail-recursion continuation-passing

我有一个函数,我想以尾递归形式编写。该函数计算通过滚动println()支持死k次来获得s总和的方式的数量。我在this answer看到了这个函数的数学解。它如下:

enter image description here

我在R中的参考递归实现是:

n

我试图以this answer的方式从延续传递样式中重新编写函数,但我没有成功。有没有办法以尾递归的形式编写这个函数?

修改

我知道R不会针对尾递归进行优化。我的问题不是R特定的,任何其他语言的解决方案同样受欢迎。即使它是一种不优化尾递归的语言。

2 个答案:

答案 0 :(得分:2)

sapply不是延续传递方式,所以你必须替换它。

这是Python中延续传递风格的翻译(另一种语言有正确的尾调用):

def sum_ways_cps(n_times, k_sum, s_side, ctn):
    """Compute the number of ways to get the sum k by rolling an s-sided die
    n times. Then pass the answer to ctn."""

    if k_sum < n_times or k_sum > n_times * s_side:
        return ctn(0)
    elif n_times == 1:
        return ctn(1)
    else:
        f = lambda j, ctn: sum_ways_cps(n_times - 1, k_sum - j, s_side, ctn)
        return sum_cps(1, s_side + 1, 0, f, ctn)

def sum_cps(j, j_max, total_so_far, f, ctn):
    """Compute the sum of f(x) for x=j to j_max.
    Then pass the answer to ctn."""

    if j > j_max:
        return ctn(total_so_far)
    else:
        return f(j, lambda result: sum_cps(j + 1, j_max, total_so_far + result, f, ctn))


sum_ways_cps(2, 7, 6, print)  # 6

答案 1 :(得分:0)

试试这个(使用递归,如果我们想要一个尾递归版本,我们需要考虑线性递归关系):

f <- function(n, k) {
  if (n == 1) {                 # base case
    return(ifelse(k<=6, 1, 0))
  } else if (k > n*6 | k < n) { # some validation
    return(0)
  } 
  else {
    # recursive calls, f(1,j)=1, 1<=j<=6, otherwise 0  
    return(sum(sapply(1:min(k-n+1, 6), function(j) f(n-1,k-j))))  
  }
}

sapply(1:13, function(k) f(2, k))
# [1] 0 1 2 3 4 5 6 5 4 3 2 1 0