簡體   English   中英

從總和為所需總數的值列表中確定所有可能的組合

[英]Determining all possible combinations from a list of values that sum to desired total

我被問到一個朋友關於如何確定一組中所有可能的值組合的編程問題可以被添加以產生所需的總數。 我有一個解決方案,但它不是優雅的(它基本上只是一系列for循環和if語句)。 我確信dplyr有一個我無法想到的解決方案,因為我知道它有多么有用,但我還沒有得到很好的解決方案。 我將在下面發布問題和我的腳本。

問題:目標上有六個環,每個環值相同。 這些值可以是1,2,3,4,5或6.您可以使用多少種不同的戒指組合來獲得9分?

所以要考慮:順序並不重要您可以根據需要使用盡可能少的值您可以多次獲得相同的值(因此9 1是完全有效的選項)

我曾經考慮過首先使用combinat包中的combn(),但是combn()不會替換值。

然后我決定使用一系列嵌套的for循環和if語句(我把它截斷到你只能使用最多6個值的地方,因為雖然我可能有空閑時間,但我不是一個關於寫循環的受虐狂允許最多9個值)。 從本質上講,它正在運行6個for循環,值得一些可能的值。 我將數字0包含在可能的值列表中以表示沒有嘗試,當我只需要2個值而不是6時(所以4 + 5 + 0 + 0 + 0 + 0在此循環中是有效輸出,但它不會能夠做4 + 5,因為它總是試圖添加更多的非零值)。

## Create a vector x with possible values
x = c(1,2,3,4,5,6)  

## Add in value 0 because I need to be able to write this dumb loop that allows many terms to be used, but also allows smaller amounts of terms to be used

x = c(x,0);x

## Creating empty data.frame to input solutions to so that I can check for uniqueness of solution
df = data.frame("a" = as.numeric(),
            "b" = as.numeric(),
            "c" = as.numeric(),
            "d" = as.numeric(),
            "e" = as.numeric(),
            "f" = as.numeric())

for (a in x){
  for (b in x){
    for (c in x){
      for (d in x){
        for (e in x){
          for (f in x){
            m = sum(a,b,c,d,e,f)
            if(m == 9) {
              p = 0
              n = c(a,b,c,d,e,f)
              if (nrow(df) == 0){
                df[1,] = n
              }
              if (nrow(df) >= 1){
                for (i in (1:nrow(df))){
                  if(setequal(n,df[i,]) == TRUE){
                    p = p+1
                    }}
                if(p == 0){
                  df = rbind(df,n)
                }
              }
            }  
          } 
        }
      }
    }
  }
}

## Convert any 0 values to NA
df[df==0] = NA

## Check Solutions
df

我創建了一個空的data.frame來存儲解決方案,然后在循環中,我創建了一個測試,以查看循環中的新解決方案是否匹配先前找到的值的組合,如果是,則不會rbind() data.frame。

我確信有一種更好的方法可以實現這一點,允許動態最大數量的值(因此在這種情況下可以通過軟編碼將每個解決方案中的最大值更改為9而不是我的硬編碼6,如果我想要的總數是5而不是9,則將其降至5)。 如果你有任何建議,使這不那么笨重,循環填補一團糟,我們將不勝感激!

你可以試試這個:

    library(modelr)
    library(dplyr)
    range = 1:6
    df = data.frame("a" = range,
              "b" =  range,
              "c" =  range,
              "d" =  range,
              "e" =  range,
              "f" =  range)
    data_grid(df,a,b,c,d,e,f) %>% 
      mutate(sum = a+b+c+d+e+f) %>% 
      filter(sum == 9) %>% nrow

這是功能:

foo <- function(sum_needed, max_value){
  range <- 1:max_value
  df = data.frame("a" = range,
                "b" =  range,
                "c" =  range,
                "d" =  range,
                "e" =  range,
                "f" =  range)
  result <- data_grid(df,a,b,c,d,e,f) %>% 
    mutate(sum = a+b+c+d+e+f) %>% 
    filter(sum == sum_needed) %>% nrow
  return(result)
}
foo(9,6)
#[1] 56
x = 1:6
mysum = 9

#Repeat each element of x as long the sum of repetitions does not exceed mysum
temp = rep(x, floor(mysum/x))

#Calculate total unique combinations of temp that sum up to mysum
sum(sapply(1:max(floor(mysum/x)),
           function(i) sum(rowSums(unique(t(combn(temp, i)))) == mysum)))
#[1] 26

以下應列出所有組合

sapply(1:max(floor(mysum/x)), function(i){
    temp2 = unique(t(combn(temp, i)))
    temp2[rowSums(temp2) == mysum,]
    })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM