【问题标题】:combinations of numbers to reach a given sum - recursive implementation in R数字组合以达到给定的总和 - R 中的递归实现
【发布时间】:2018-03-01 17:55:01
【问题描述】:

我要做的就是实现给定here的解决方案(python中的那个) 在 R。 我不太习惯在 R-Studio 中进行调试,但即使在我尝试过之后,我仍然无法弄清楚为什么我的代码不起作用。基本上(使用提供的示例输入)我得到了运行所有数字的函数,然后它陷入了一种无限循环(或函数)中。有人可以为我指出正确的方向吗?

subset_sum <- function(numbers, target, partial = numeric(0)){
  s <-  sum(partial,na.rm = TRUE)

  # check if the partial sum equals to target
  if (s == target){
    cat("sum(",partial,")","=",target)
  }
  else if (s >= target) {
    return() # if we reach the number why bother to continue

  }
  else {

    for(i in 1:length(numbers)){
      n <-  numbers[i]
      remaining <- numbers[i+1:length(numbers)]
      subset_sum(remaining, target, partial = append(partial,n))
    }
      }
}

subset_sum(c(3,9,8,4,5,7,10),15)

当不在调试模式下运行时,它会给我这些错误:

Error: node stack overflow
Error during wrapup: node stack overflow

【问题讨论】:

  • 我可能理解错了,但是你怎么能在你的函数中使用函数subset_sum,也叫subset_sum
  • @Visser:它被称为 recursion,这是问题的标签之一。这是一个有趣的话题;做一点研究,玩得开心。
  • 试试remaining &lt;- numbers[(i+1):length(numbers)]。注意:+ 的运算符优先级
  • @MrFlick:谢谢!看来这是我的问题。

标签: r function recursion


【解决方案1】:

这是R中的递归实现

subset_sum = function(numbers,target,partial=0){
  if(any(is.na(partial))) return()
  s = sum(partial)
  if(s == target) print(sprintf("sum(%s)=%s",paste(partial[-1],collapse="+"),target))
  if(s > target) return()
  for( i in seq_along(numbers)){
    n = numbers[i]
    remaining = numbers[(i+1):length(numbers)]
    subset_sum(remaining,target,c(partial,n))
  }
}

当 i+1 > length(numbers) 并返回 NA 时,我必须在 R 中从 python 添加一个额外的 catch 来处理。

> subset_sum(c(3,9,8,4,5,7,10),15)
[1] "sum(3+8+4)=15"
[1] "sum(3+5+7)=15"
[1] "sum(8+7)=15"
[1] "sum(5+10)=15"

我认为(但我不确定)您的问题是在递归函数中嵌套 if/else if 逻辑。有趣的是,当我将 if(i+1 &gt; length(numbers)) return() 放在 for 循环中时,它破坏了功能,所以我没有得到所有正确的答案 - return 需要在递归之外。

【讨论】:

  • 谢谢,我使用了sprintf() 方法而不是cat,因为这样更方便。但实际上我的问题是(我有点尴尬)在递归中对remaining 的赋值中i+1 周围的括号。
  • @Corel 如果我的回答是正确的,我希望你这样标记它!
  • 你的回答没有错,但 MrFlick 在上面 cmets 部分的回答确实让我遇到了我的代码遇到的问题
【解决方案2】:

这不是递归函数,但它利用了 R 处理矩阵/数组类型数据的能力。在#之后显示一些输出

v <- c(3,9,8,4,5,7,10)
v <- sort(v)
# [1]  3  4  5  7  8  9 10
target <- 15
# we don't need to check more than at most 4 numbers since 3+4+5+7 (the smallest numbers) is greater than 15
mincombs <- min(which(cumsum(v) > target))  
# [1] 4
Combs <- combn(v, mincombs)  # make combinations of numbers
ans <- mapply(function(x,y) ifelse(y > 0, paste0(paste0(Combs[1:y,x], collapse="+"), "=", target), NA), 1:ncol(Combs), apply(Combs, 2, function(I) which(cumsum(I) == target)))
ans <- unlist(ans[lengths(ans) > 0])
# [1] "3+4+8=15" "3+4+8=15" "3+5+7=15" "3+5+7=15" "3+5+7=15" "7+8=15"

在函数中

myfun <- function(V, target) {
                V <- sort(V)
                mincombs <- min(which(cumsum(V) > target))
                Combs <- combn(V, mincombs)
                ans <- mapply(function(x,y) ifelse(y > 0, paste0(paste0(Combs[1:y,x], collapse="+"), "=", target), NA), 1:ncol(Combs), apply(Combs, 2, function(I) which(cumsum(I) == target)))
                ans <- unlist(ans[lengths(ans) > 0])
                return(ans)
         }

myfun(V = c(3,9,8,4,5,7,10), target = 15)
myfun(V = c(3,9,8,4,5,7,10,12,4,32),target = 20)

【讨论】:

  • myfun(V = c(3,9,8,4,5,7,10,12,4,32),target = 20) 不起作用 - 它给出了错误的组合。
  • 很抱歉。现在就试试。我忘了把15 换成target
猜你喜欢
  • 2023-01-09
  • 1970-01-01
  • 2011-06-05
  • 2021-01-02
  • 2019-05-24
  • 1970-01-01
  • 2021-06-19
  • 2012-12-05
相关资源
最近更新 更多