可以用 R6 写一个模拟框架,可能更贴近楼主所说的“检查源头”的意思:
library(R6)
CargoSimulator <- R6Class(
"CargoSimulator",
private = list(
cargo_A = 30,
cargo_B = 20,
shipments = c(4, 6, 6, 7, 8, 9, 10),
trace = data.frame()
),
public = list(
initialize = function() {
private$trace <- data.frame(Quantity = private$shipments, Source = NA)
},
trace_source = function() {
backtrack <- function(index) {
if (index > nrow(private$trace)) {
return(TRUE)
}
qty <- private$trace$Quantity[index]
sources <- sample(c("A", "B"))
for (source in sources) {
if (source == "A" && private$cargo_A >= qty) {
private$cargo_A <- private$cargo_A - qty
private$trace$Source[index] <- "A"
if (backtrack(index + 1)) {
return(TRUE)
}
private$cargo_A <- private$cargo_A + qty # backtrack
} else if (source == "B" && private$cargo_B >= qty) {
private$cargo_B <- private$cargo_B - qty
private$trace$Source[index] <- "B"
if (backtrack(index + 1)) {
return(TRUE)
}
private$cargo_B <- private$cargo_B + qty # backtrack
}
}
private$trace$Source[index] <- NA # backtrack
return(FALSE)
}
if (backtrack(1)) {
return(private$trace)
} else {
warning("No valid configuration found.")
return(NULL)
}
}
)
)
unique_config <- list()
for (i in 1:10000) {
simulator <- CargoSimulator$new()
config <- simulator$trace_source()
if (!is.null(config)) {
if (!any(sapply(unique_config, identical, config))) {
unique_config[[length(unique_config) + 1]] <- config
}
}
}
unique_config