3

我们有一定数量,例如 300 个单位。这个数量应该尽可能均匀地分布在 40 个“插槽”上。如果每个插槽都相同,那将很容易-因此每个插槽将是 7,5。然而,插槽的大小各不相同,我们不能“填充”超过它的“大小”允许的范围,例如如果它只有 5 个。我们不能“填充”的内容我们必须在其他插槽上分配更多。

我有一些基本的想法,但我离成为专家还很遥远,希望有一种简单的方法来解决这个问题。例如,这可能是什么样子。在数组“a”中,值代表插槽可以采用的最大值。a[i] 是第 i 个时隙的最大值。“b”是我们必须分配的整体,例如 300。

 # developing slots and their "size"
 a <- rnorm(40,10,4)
 sum(a)

 # overall sum to distribute
 b <- 300 

也许可以按升序对值进行排序,然后可以通过双 for 循环使用它。a[,2] 成为“填充”金额的列。

 for i in 1:40
 {a[i,2] <- a[1,2]*40
 b <- a [1,2]*40}

 for i in 2:40
 {a[i,2] <- a[1,2]*39
 b <- a[1,2]*39}

etc.

我不确定如何将两个 for 循环放在一起,以及这是否是一个足够的解决方案。很高兴听到你的想法。谢谢!

4

2 回答 2

2

第一个版本,使用 while 循环:

optimal.fill <- function(a, b) {
  stopifnot(sum(a) >= b)

  d <- rep(0, length(a))
  while(b > 0) {
    has.room  <- a > 0
    num.slots <- sum(has.room)
    min.size  <- min(a[has.room])
    add.size  <- min(b / num.slots, min.size)
    d[has.room] <- d[has.room] + add.size
    a[has.room] <- a[has.room] - add.size
    b <- b - num.slots * add.size
  }
  return(d)
}

这第二个版本有点难以理解,但我觉得更优雅:

optimal.fill <- function(a, b) {
  stopifnot(sum(a) >= b)

  slot.order   <- order(a)
  sorted.sizes <- a[slot.order]
  can.fill     <- sorted.sizes * rev(seq_along(a))
  full.slots   <- slot.order[which(cumsum(can.fill) <= b)]

  d <- rep(0, length(a))
  d[ full.slots] <- a[full.slots]
  d[!full.slots] <- (b - sum(a[full.slots])) /
                    (length(a) - length(full.slots))

  return(d)
}
于 2012-06-29T00:54:31.040 回答
1

这是另一种选择:

optimal.fill2 <- function(a,b) {
  o <- rank(a)
  a <- sort(a)
  ca <- cumsum(a)
  foo <- (b-ca)/((length(a)-1):0)
  ok <- foo >= a
  a[!ok] <- foo[max(which(ok))]
  a[o]
}
于 2012-06-29T02:31:03.883 回答