5
$\begingroup$

My question is to solve a very basic problem related to the allocation of slots. Say there are 20 teams with 10 persons in each team.

I have 150 open slots every day (5 days a week) for those 20 teams but I cannot accommodate 200 arrivals every day.

  1. But, I need to accommodate everyone in the team in the open slot at least for 3 days or a maximum of 5 days.

  2. Accommodation should not be biased by allocating more people from one single team (say 10 people from team 1, 2 people from team 2). But it should be balanced say 10 people from team 1, 8 people from team 2, 7 people from team 3. But should not be less than 6.

Any mathematical or probabilistic or stochastic model is preferred. Even if the simple solution to this problem is also much appreciated.

$\endgroup$
2
  • $\begingroup$ if I go with random, there is a chance that a person cannot be picked for the entire week, I need to accommodate everyone for at least three days a week. $\endgroup$
    – StatsUser
    Commented Nov 30, 2021 at 19:05
  • $\begingroup$ Fun little task. I got you a solution below in base R I tried to keep it simple so it can be translated to any language easily. $\endgroup$
    – usεr11852
    Commented Dec 2, 2021 at 4:58

1 Answer 1

1
$\begingroup$

Please find a quick solution below. Here, simply cycling carefully through the group of users is fine.

In the solution below, all groups have always at least 6 people served per day. More specifically we always serve either 7 or 8 people per group for Days 1 to 3; in Day 4 might have a group $i$ with "only" 6 people served due to random variation of group $i$ having repeatedly 8 people served in the Days 1 to 3; in Day 5 we once again have at least 7.

The code is commented extensively but let me know if you want any clarifications.

The main thing is to remember the pigeonhole principle when working through the steps - it essentially what makes this work at Day 4. Otherwise Days 1 to 3 are "usual" stratified random sampling - the stratification being done on the team/group level.

# Setting up the data.frame to hold the results
set.seed(3)
people <- expand.grid(letters[1:20], 1:10) 
colnames(people) <- c('group','index')
people$uid <- apply(people,1, function(x) paste0("", x[1], x[2]))

# Day 1:
# Pick the first 7 people from each group (7 * 20 = 140)
people$day1 <- people$index %in% 1:7 #change to sample(size=7,x=10) for something more random
# Pick the remain 10 at random from the ones not selected but only additional one from each group! 
for (my_group in sample(unique(people$group), size = 10, replace = FALSE)){
  grp_indx <- which( (FALSE == people$day1) & (my_group == people$group))
  people$day1[ sample(grp_indx,replace = FALSE, size =1)] = TRUE 
}


# Day 2:
# Pick the 50 people not selected in Day 1
people$day2 <- !people$day1
# Pick the remain 100 at random from the ones not selected in the previous step (i.e. the ones who were served in Day 1)
# We do this in two steps
# Step 1: We sample in a stratified manner by group to ensure we never have a group with less than 7 served on Day 2 either
for (my_group in unique(people$group)){
  grp_indx <- which( (FALSE == people$day2) & (my_group == people$group))
  people$day2[ sample(grp_indx,replace = FALSE, size =  length(grp_indx) - (10-7)) ] = TRUE 
}
# Step 2: Pick the remain 10 at random from the ones not selected but only additional one from each group! 
for (my_group in sample(unique(people$group), size = 10, replace = FALSE)){
  grp_indx <- which( (FALSE == people$day2) & (my_group == people$group))
  people$day2[ sample(grp_indx,replace = FALSE, size =1)] = TRUE 
}


# Day 3:
# Pick the 100 people who were not selected in both Day 1 & 2 already (ensuring everyone get at least two servings by day 3)
people$day3 <- !(people$day1 & people$day2)
# Pick the remain 50 at random from the ones not selected in the previous step (i.e. the ones who were served in Day 1 &2)
# We do this in two steps
# Step 1: We sample in a stratified manner by group to ensure we never have a group with less than 7 served on Day 3 either
for (my_group in unique(people$group)){
  grp_indx <- which( (FALSE == people$day3) & (my_group == people$group))
  people$day3[ sample(grp_indx,replace = FALSE, size =  length(grp_indx) - (10-7)) ] = TRUE 
}
# Step 2: Pick the remain 10 at random from the ones not selected but only one per group! 
for (my_group in sample(unique(people$group), size = 10, replace = FALSE)){
  grp_indx <- which( (FALSE == people$day3) & (my_group == people$group))
  people$day3[ sample(grp_indx,replace = FALSE, size =1)] = TRUE 
}


# Day 4:
# Pick the people who were not already served three times
people$day4 <- !(people$day1 + people$day2+ people$day3 == 3)
# At this point everyone has been selected exacty three times
all(rowSums(people[,c('day1','day2','day3','day4')]) == 3)


# Day 5: # Repeat Day 1 effectively
# Pick the first 7 people from each group (7 * 20 = 140)
people$day5 <- people$index %in% sample(size=7,x=10) # something more random than just the first 7 people per group
# Pick the remain 10 at random from the ones not selected / we don't care to stratify at this point really
people$day5[sample(which(FALSE == people$day5), size = 10, replace = FALSE)] = TRUE
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.