2014-11-21 10 views
8

Desidero generare un insieme di permutazioni di sfere n negli intervalli m. La seguente serie di elenchi nidificati genera tali permutazioni.Generazione di tutte le permutazioni di sfere N nei contenitori M

n <- 3 
m <- 4 
v <- rep(0,m) 
for (i in n:0){ 
    for (j in (n-sum(i)):0){ 
    for (k in (n-sum(i,j)):0){ 
     for (l in (n - sum(i,j,k)):0){ 
     v <- c(i,j,k,l) 
     print(v) 
     if (sum(v) == n){ break } 
     } 
    } 
    } 
} 

che stampa la soluzione:

[1] 3 0 0 0 
[1] 2 1 0 0 
[1] 2 0 1 0 
[1] 2 0 0 1 
[1] 1 2 0 0 
[1] 1 1 1 0 
[1] 1 1 0 1 
[1] 1 0 2 0 
[1] 1 0 1 1 
[1] 1 0 0 2 
[1] 0 3 0 0 
[1] 0 2 1 0 
[1] 0 2 0 1 
[1] 0 1 2 0 
[1] 0 1 1 1 
[1] 0 1 0 2 
[1] 0 0 3 0 
[1] 0 0 2 1 
[1] 0 0 1 2 
[1] 0 0 0 3 

Il numero totale di permutazioni sarà choose(n+m-1,m-1), e l'ordine delle permutazioni non importa a me. Ma sto facendo fatica a farlo diventare una funzione che può prendere un numero arbitrario di contenitori. (Non rovinerò il pozzo con i miei tentativi, è solo un guazzabuglio di anelli annidati però.) Quindi, se qualcuno più sdolcinato di me potrebbe tradurre i loop nidificati in una funzione, lo apprezzerei.

Oppure se è già disponibile una funzione per eseguire questo tipo di permutazione (o un algoritmo diverso da seguire), sarei felice di essere informato a riguardo. Preferirei un approccio che non generi permutazioni superflue (qui non si sommano a n) e poi li scarto, ma per piccoli problemi come questo una soluzione che lo farebbe essere accettabile.

+2

Un approccio, certamente non il più efficiente ma migliore dei loop multipli annidati, sarebbe: 'x <- expand.grid (rep (elenco (0: n), m)); x [rowSums (x) == n,] ' –

+0

Grazie @beginneR! Avevo difficoltà a usare 'expand.grid' come volevo, quell'esempio lo risolve un po 'per me. –

+2

Mai ** mai ** reinventare una ruota evidente. Ci sono tonnellate di pettine e strumenti simili a perm in vari pacchetti. (ad esempio, la risposta di Josh) –

risposta

10
library(partitions) 
compositions(3,4) 

# [1,] 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 0 1 2 0 1 0 0 1 2 0 1 0 0 1 0 0 
# [3,] 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 1 1 1 1 1 1 2 2 2 3 
+0

Grazie, la libreria 'partitions' non è mai comparsa nei miei tentativi di ricerca. Guardando alla fonte, non avrei mai avuto questa soluzione. –

1

Di seguito si fornisce una risposta leggermente differente, ma equivalente utilizzando un pacchetto più generale iterpc

m = 4; n = 3 
library(iterpc) 
I = iterpc(m, n, replace=T) 
getall(I) 

L'uscita è i numeri di intervalli per le n palline.

 [,1] [,2] [,3] 
[1,] 1 1 1 
[2,] 1 1 2 
.... 
.... 
[18,] 3 3 4 
[19,] 3 4 4 
[20,] 4 4 4 

La prima riga significa che le 3 palle sono tutti da bin 1 mentre l'ultima riga significa che le 3 palle sono tutti da bin 4.

Si può facilmente produrre il risultato desiderato contando il numero di 1, 2, 3 e 4. E puoi anche usare l'iteratore per generare il risultato in sequenza.

count <- function(x){ 
    as.numeric(table(factor(x, levels=1:m))) 
} 
I = iterpc(m, n, replace=T) 


> count(getnext(I)) 
[1] 3 0 0 0 
> count(getnext(I)) 
[1] 2 1 0 0 
> count(getnext(I)) 
[1] 2 0 1 0 
> count(getnext(I)) 
[1] 2 0 0 1 
Problemi correlati