tipos sumatoria studio propiedades con combinatoria combinaciones calculadora r numbers combinatorics

sumatoria - Suma parcial combinatoria



sumatoria con combinatoria propiedades (3)

Estoy buscando en R una función partial.sum() que toma un vector de números y devuelve un vector ordenado ascendente de todas las sumas parciales:

test=c(2,5,10) partial.sum(test) # 2 5 7 10 12 15 17 ## 2 is the sum of element 2 ## 5 is the sum of element 5 ## 7 is the sum of elements 2 & 5 ## 10 is the sum of element 10 ## 12 is the sum of elements 2 & 10 ## 15 is the sum of elements 5 & 10 ## 17 is the sum of elements 2 & 5 & 10


Aquí hay un enfoque iterativo usando combn para producir combinaciones en suma. Funciona para vectores de mayor longitud que 1.

partial.sum <- function(x) { sort(unique(unlist(sapply(seq_along(x), function(i) colSums(combn(x,i)))))) } ## [1] 2 5 7 10 12 15 17

Para manejar longitudes menores a 2, prueba la longitud:

partial.sum <- function(x) { if (length(x) > 1) { sort(unique(unlist(sapply(seq_along(x), function(i) colSums(combn(x,i)))))) } else { x } }

Algunos tiempos, fuera de rbenchmark , que no están del todo de acuerdo con los resultados de Flodel. Modifiqué el código de Dason, eliminé los comentarios y agregué una llamada a unique . La versión de mi código es la primera, sin el if . El código de Flodel es un claro ganador aquí.

> test <- 1:10 > benchmark(matthew(test), flodel(test), dason(test), replications=100) test replications elapsed relative user.self sys.self user.child sys.child 3 dason(test) 100 0.180 12.857 0.175 0.004 0 0 2 flodel(test) 100 0.014 1.000 0.015 0.000 0 0 1 matthew(test) 100 0.244 17.429 0.242 0.001 0 0 > test <- 1:20 > benchmark(matthew(test), flodel(test), dason(test), replications=1) test replications elapsed relative user.self sys.self user.child sys.child 3 dason(test) 1 5.231 98.698 5.158 0.058 0 0 2 flodel(test) 1 0.053 1.000 0.053 0.000 0 0 1 matthew(test) 1 2.184 41.208 2.180 0.000 0 0 > test <- 1:25 > benchmark(matthew(test), flodel(test), dason(test), replications=1) test replications elapsed relative user.self sys.self user.child sys.child 3 dason(test) 1 288.957 163.345 264.068 23.859 0 0 2 flodel(test) 1 1.769 1.000 1.727 0.038 0 0 1 matthew(test) 1 75.712 42.799 74.745 0.847 0 0


Aquí hay uno que usa la recursión. (No hacer afirmaciones de que sea eficiente tampoco)

partial.sum <- function(x) { slave <- function(x) { if (length(x)) { y <- Recall(x[-1]) c(y + 0, y + x[1]) } else 0 } sort(unique(slave(x)[-1])) } partial.sum(c(2,5,10)) # [1] 2 5 7 10 12 15 17

Editar: bueno, resulta que es un poco más rápido de lo que pensaba:

x <- 1:20 microbenchmark(flodel(x), dason(x), matthew(x), times = 10) # Unit: milliseconds # expr min lq median uq max neval # flodel(x) 86.31128 86.9966 94.12023 125.1013 163.5824 10 # dason(x) 2407.27062 2461.2022 2633.73003 2846.2639 3031.7250 10 # matthew(x) 3084.59227 3191.7810 3304.36064 3693.8595 3883.2767 10

(Agregué el sort y / o unique para las funciones de dason y matthew cuando corresponde para una comparación justa.)


Probablemente esto no se escale demasiado bien y no tenga en cuenta posibles duplicados en el vector de entrada o duplicados en la respuesta. Puede usar el unique más adelante si eso le preocupa.

partial.sum <- function(x){ n <- length(x) # Something that will help get us every possible subset # of the original vector out <- do.call(expand.grid, replicate(n, c(T,F), simplify = F)) # Don''t include the case where we don''t grab any elements out <- head(out, -1) # ans <- apply(out, 1, function(row){sum(x[row])}) # As flodel points out the following will be faster than # the previous line ans <- data.matrix(out) %*% x # If you want only unique value then add a call to unique here ans <- sort(unname(ans)) ans }