2014-09-25 89 views
2

此問題與另一個問題R:sample()密切相關。我想在R中找到一種方式來列出所有k個數的排列,其和爲k,其中每個數從0:k中選擇。如果k = 7,我可以從0,1,...,7中選擇7個數字。一個可行的解決方案是0,1,2,3,1,0,0另一個是1,1,1,1,1,1,1。我不想生成所有的排列,因爲如果k只是比7大,這個爆炸。列出k個數字的所有排列,取自0:k,表示總和爲k

當然在第k = 7實施例我可以使用以下:

perms7<-matrix(numeric(7*1716),ncol=7) 
count=0 
for(i in 0:7) 
    for(j in 0:(7-i)) 
     for(k in 0:(7-i-j)) 
      for(l in 0:(7-i-j-k)) 
       for(n in 0:(7-i-j-k-l)) 
        for(m in 0:(7-i-j-k-l-n)){ 
          res<-7-i-j-k-l-n-m 
          count<-count+1 
          perms7[count,]<-c(i,j,k,l,n,m,res) 
         } 
head(perms7,10) 

但是我怎樣可以概括這種方法考慮到任意k,而無需編寫(K-1)環路? 我試圖想出一個遞推方案:

perms7<-matrix(numeric(7*1716),ncol=7) #store solutions (adjustable size later) 
k<-7 #size of interest 
d<-0 #depth 
count=0 #count of permutations 
rec<-function(j,d,a){ 
    a<-a-j #max loop 
    d<-d+1 #depth (posistion) 
    for(i in 0:a) { 
     if(d<(k-1)) rec(i,d,a) 
     count<<-count+1 
     perms7[count,d]<<-i 
     perms7[count,k]<<-k-sum(perms7[count,-k]) 
    } 
} 
rec(0,0,k) 

但卡住了,我不太確定這是正確的道路要走。不知道是否有任何「魔術」R函數對於這個(雖然非常具體)的問題或者只是其中的一部分而言是整齊的。

在K = 7的情況下,所有的2.097.152置換和1.716該總和爲k = 7可以通過找到:

library(gtools) 
k=7 
perms <- permutations(k+1, k, 0:k, repeats.allowed=T) #all permutations 
perms.k <- perms[rowSums(perms) == k,] #permutations which sums to k 

對於k = 8有43.046.721排列,但我只想列出6.435。 任何幫助,非常感謝!

+0

我相信這是有關漢諾塔的問題。包'fun'和'ref'有解決這個問題的功能。 – James 2014-09-25 09:17:54

+0

我不明白這與河內塔問題有何關係,請您詳細說明一下?基本上我只需要計算Z^k中超平面的基數。 – 2014-09-25 09:46:41

+0

這是k-tile,k-peg ToH所有可能狀態的空間。 ToH的最佳解決方案顯然不會試圖遍歷所有狀態,但如果您尋找最佳次優解決方案,您應該得到答案。 – James 2014-09-25 09:53:02

回答

5

有一個軟件包內...

require(partitions) 
parts(7)         
#[1,] 7 6 5 5 4 4 4 3 3 3 3 2 2 2 1 
#[2,] 0 1 2 1 3 2 1 3 2 2 1 2 2 1 1 
#[3,] 0 0 0 1 0 1 1 1 2 1 1 2 1 1 1 
#[4,] 0 0 0 0 0 0 1 0 0 1 1 1 1 1 1 
#[5,] 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 
#[6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 
#[7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 

你似乎是在尋找compositions()。例如對於K = 4

parts(4) 

#[1,] 4 3 2 2 1 
#[2,] 0 1 2 1 1 
#[3,] 0 0 0 1 1 
#[4,] 0 0 0 0 1 

compositions(4,4)                   
#[1,] 4 3 2 1 0 3 2 1 0 2 1 0 1 0 0 3 2 1 0 2 1 0 1 0 0 2 1 0 1 0 0 1 0 0 0 
#[2,] 0 1 2 3 4 0 1 2 3 0 1 2 0 1 0 0 1 2 3 0 1 2 0 1 0 0 1 2 0 1 0 0 1 0 0 
#[3,] 0 0 0 0 0 1 1 1 1 2 2 2 3 3 4 0 0 0 0 1 1 1 2 2 3 0 0 0 1 1 2 0 0 1 0 
#[4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 4 

而只是爲了檢查你的數學... :-)

ncol(compositions(8,8)) 
#[1] 6435 
+0

這非常整齊。我將研究composition()如何工作以確保它不僅計算所有排列和子集。謝謝! – 2014-09-25 10:46:50

+0

@ J.R。它非常快!您需要下載源代碼,因爲我認爲您需要檢查pacakge中的C函數'allblockparts'。 – 2014-09-25 10:48:52

+0

是的,它工作的很好,所以我很有信心它沒有列出所有的排列第一!您應該考慮將其添加爲開始時提到的鏈接問題的解決方案。我會看看'allblockparts'。再次感謝你! – 2014-09-25 10:54:36

相關問題