1

I want to create an array, then assign a value to each place until the sum of values in the array equals a given total. Once the maximum value is reached the rest of the array can be 0. So to start:

years <- 20 # total length of array

N <- array(0, years) # make array

tot <- 10 # Total I want to stop at

max.size <- 3 # maximum value to put in the array

So the result may look something like: N = c(1,3,0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0)

I think a while statement would work, similar to this question, but not sure how to get there. Also, I think this question has the pieces I need, but am struggling to put them into my context.

random.sample <- function(x) {  repeat {
# do something
i <- sample(0:max.size, 1)
x <- i
# exit if the condition is met
if (sum(x) == tot) break } return(x) }        
random.sample(N)

Thanks for your time.

tjr
  • 607
  • 2
  • 7
  • 20
  • `==` seems like a bad choice. What happens if you skip over the total? Say you have 1,2,3,2,1 so the total is 9, and then your next value is 3, you jump to 12 and never `== 10`. I'd suggest `sum(x) >= 10` as your break condition. – Gregor Thomas Feb 09 '23 at 19:34

1 Answers1

2

A simple function using cumsum and ifelse would do the job without requiring costly loops. The last clause just ensures the the numbers add to tot

f <- function(len, tot, max.size) {
  x <- sample(0:max.size, len, replace = TRUE)
  res <- ifelse(cumsum(x) > tot, 0, x)

  if(sum(res) < tot) {
    res[(cumsum(res) == sum(res)) & res == 0][1] <- tot - sum(res)
  }
  res
}

Testing

f(len = 20, tot = 10, max.size = 3)
#> [1] 3 3 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87