R:从列表中随机选择项目



我正在使用R编程语言。我想创建一个问题,其中:

  • 有4个人:"person 1", "person 2", "person 3" ,"person 4"

  • 有食品清单:"pizza", "apples", "tacos", "ice cream", "grapes", "olives", "sushi", "chocolate", "cake", "nachos", "pasta", "cookies", "popcorn", "soup"

  • 一年中有天数列表:1 to 365

在这个问题中,人员列表是随机排序的。这个列表的顺序决定了谁可以"第一个选择"。

根据名单的顺序,排在最前面的人将被随机分配4个数字:

  • Rand_1_1(第一人,第一个随机数):第一个随机数将决定"食物"的数量;第一个人可以选择(例如3)

  • Rand_1_2(第一人,第二个随机数):第二个随机数将决定哪些"食品";第一个人要按"食物"的数量拣。对应于"Rand_1_1"(如"tacos","nachos","soup")

  • Rand_1_3(第1个人,第三个随机数):第三个随机数将决定第一个人的天数

  • Rand_1_4(第一个人,第四个随机数):第四个随机数将决定第一个人的天数的另一个界限(例如,第一个人可能被分配天数为"41至160")。

这是随机数分配过程,然后为所有人完成:Rand_1_1, Rand_1_2, Rand_1_3, Rand_1_4, Rand_2_1, Rand_2_2, Rand_2_3, Rand_2_4, Rand_3_1, Rand_3_2, Rand_3_3, Rand_3_4, Rand_4_1, Rand_4_2, Rand_4_3, Rand_4_4

然而,有一个逻辑约束:
  • "person"不能选择"食物";已经被"人"选择的东西;(例如,如果第一个人被选中在第二个人之前选择,如果第一个人选择"披萨";那么第二个人就不能选择"pizza")

  • "person"不能选择"天数范围";这已经被"人"选择了。在他们面前

  • 4个人都选完了,就可以了有些"食物"还有一些"日期范围">可以保持未选中. 另一方面,假设第一个人先选,他碰巧选了所有的"食物"。——当然,其他人就没有"食物"了。同样的逻辑也适用于"日期范围"。

现在,我正试图在R中编码:

首先,加载库:

#load libraries
library(dplyr)
library(gtools)

第二,我创建了数据:

#create data
#variable 1: days of the year 
days <- 1:365
#variable 2 : food
food <- c("pizza", "apples", "tacos", "ice cream", "grapes", "olives", "sushi", "chocolate", "cake", "nachos", "pasta", "cookies", "popcorn", "soup")
food_data <- data.frame(food)
food_data$id <-  1:nrow(food_data)
# people 
people <- c("person 1", "person 2", "person 3" ,"person 4")

3,我创建了人们选择的顺序:

# randomize order of people : this decides the order of who picks "days" and "food"
set.seed(123)
order_of_people = permute(people)
# in this example, "person 3" will pick first, "person 4" will pick second, "person 1" will pick third and "person 2" will pick last
order_of_people
[1] "person 3" "person 4" "person 1" "person 2"

我的问题:我知道如何给每个人分配一个随机数,但我不知道如何分配随机数以使逻辑约束得到尊重。例如:

#choices for person 3 (according to the random seed, person 3 will pick 5 food items)
set.seed(120)
dim = dim(food_data)
#number of items selected by person 3
Rand_3_1 <- sample.int(dim[1], 1)
#which food items selected by person 3 (corresponding to the food_id : "3, 9, 6, 7, 4")
set.seed(120)
Rand_3_2 = c( sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1),  sample.int(dim[1], 1), sample.int(dim[1], 1))
#which days selected by person 3 (according to this random seed, "65 to 87")
set.seed(120)
Rand_3_3 <- sample.int(365, 1)
Rand_3_4 <- sample.int(365, 1)
因此,我可以创建"选择框架"每个人:
#Person 1
Rand_1_1 <- sample.int(dim[1], 1)
Rand_1_2 = c( #fill randomly with amount of items specified by Rand_1_1)
Rand_1_3 <- sample.int(365, 1)
Rand_1_4 <- sample.int(365, 1)
#Person 2
Rand_2_1 <- sample.int(dim[1], 1)
Rand_2_2 = c( #fill randomly with amount of items specified by Rand_2_1)
Rand_2_3 <- sample.int(365, 1)
Rand_2_4 <- sample.int(365, 1)

#Person 3
Rand_3_1 <- sample.int(dim[1], 1)
Rand_3_2 = c( #fill randomly with amount of items specified by Rand_3_1)
Rand_3_3 <- sample.int(365, 1)
Rand_3_4 <- sample.int(365, 1)
#Person 4
Rand_4_1 <- sample.int(dim[1], 1)
Rand_4_2 = c( #fill randomly with amount of items specified by Rand_4_1)
Rand_4_3 <- sample.int(365, 1)
Rand_4_4 <- sample.int(365, 1)

但我不知道如何做到这一点,使逻辑约束得到尊重。最后,我想制作这样的东西:

#desired results
Person 1 : "apples, tacos" and "4-51"
Person 2: "cookies, nachos, cake, olives", and "56-180"
Person 3: "ice cream", and "200-214"
Person 4: "sushi, popcorn" and "350-365"

谁能告诉我怎么做这个?

感谢

这似乎很简单,除非我错过了什么,你有一个食物和日期的列表,所以每次你通过一个人的时候,只要跟踪可用的选项,只从这些选项中选择:

## initialize the inputs
set.seed(1)
foods <- letters[1:20]
nfoods <- sample(5, 4)
tmp <- list(unpicked = list(food = foods, days = 1:365))
## run it
tmp <- lapply(nfoods, function(x) tmp <<- f(tmp$unpicked$food, x, tmp$unpicked$days))
## summarize it
res <- sapply(seq_along(tmp), function(ii) {
x <- tmp[[ii]]
x <- sprintf('person %s: "%s" and "%s"', ii, toString(x$picked$food),
paste0(x$picked$days, collapse = '-'))
cat(x, sep = 'n')
invisible(x)
})
# person 1: "b" and "270-299"
# person 2: "s, a, k, g" and "306-336"
# person 3: "m, t, h" and "42-89"
# person 4: "j, f, q, o, l" and "129-210"

f <- function(food, n, days) {
# f(1:4, 3, 1:10)
food1 <- sample(food, n)

days1 <- split(days, cumsum(is.na(days)))
days1 <- sample(Filter(function(x) length(x) > 2, days1), 1)[[1]]
days1 <- sort(sample(sort(days1), 2))

days[do.call('seq', as.list(days1))] <- NA

list(
picked = list(food = food1, days = days1),
unpicked = list(food = setdiff(food, food1), days = days)
)
}