【问题标题】:All combinations of summing a vector of numbers together将数字向量相加的所有组合
【发布时间】:2021-03-30 13:09:07
【问题描述】:

鉴于我有向量和目标编号

target.mountain <- 10

Roll_dice <- sample(1:6, 4, replace=TRUE)

使用Roll_dice 制作 以[1] 6, 5, 3, 2为例

如何通过将Roll_dice 中的 2、3 或 4 个值组合到一个列表中来生成 Roll_dice 中所有数字的列表以及将它们加在一起的所有方法

例如[1] 2, 3, 5, 5, 6, 7, 11, ....

【问题讨论】:

  • 这听起来像XY-problem...您要解决的问题(在这个问题背后)是什么。 target.mountain有什么用?
  • 虽然我不熟悉你所说的 XY 问题,但我正在尝试创建一个 If 语句,如果 target.mountain 的值可以从 4 次掷骰子中创建,则完成某个动作如果不做其他事情。我试图简化问题,因为我一直被否决:(
  • 在我的原始评论中添加了一个链接。一个 XY 问题是当有人要求 X 时,因为他相信这会帮助他解决 Y……但情况并非总是如此……最好是解释 Y。
  • 目前我有代码,它采用给定的掷骰子,然后尝试从 4 个值中创建尽可能多的 'target.mountain' 值(没有替换)。如果未用于形成“target.mountain”值的值不在 5:10 范围内,则将它们相加以创建该范围内的值。如果这不可能,那么只需返回创建的 'target.mountain' 值和 Roll_dice 中未使用的值
  • 它来自一个名为 Mountain goats 的游戏,其中 4 个骰子被滚动形成 5:10 的数字,然后可以用作“移动”。所以我的代码旨在针对特定的山脉(在这个问题之前的给定条件下)。如果您可以在另一座山上移动(因为其他两个值在 5:10 范围内),那么您可以一次在多座山上移动。

标签: r combinations combn


【解决方案1】:

我想让你看看RccpAlgos-package,它有一些很棒(而且速度很快!)的函数,可以对有约束的组合/排列进行快速操作。

更新

library(RcppAlgos)
library(vecsets)
library(data.table)

target.mountain <- 10
Roll_dice       <- c(5, 5, 3, 2)

L <- lapply( 2:4, function(x) {
  as.data.table(comboGeneral( Roll_dice, 
                x, 
                constraintFun = "sum", 
                comparisonFun = "==", 
                limitConstraints = target.mountain ),
                keep.rownames = TRUE )
})
# [[1]]
# V1 V2
# 1:  5  5
# 
# [[2]]
# V1 V2 V3
# 1:  2  3  5

#so 5-5 of 2-3-5 can be chosen to get to 10

#remaining dice
DT <- data.table::rbindlist( L, fill = TRUE )

remains <- lapply( transpose(DT), function(x) {
  v <- as.vector(x)
  v <- v[ !is.na(v) ]
  sum( vecsets::vsetdiff( Roll_dice, v) )
})

remains
#witrh leftovers:
# $V1
# [1] 5
# 
# $V2
# [1] 5

旧答案

library(RcppAlgos)
target.mountain <- 10
Roll_dice <- c(6, 4, 5, 5)
sapply( 2:4, function(x) {
  comboGeneral( Roll_dice, 
                x, 
                constraintFun = "sum", 
                comparisonFun = "==", 
                limitConstraints = target.mountain )
})

# [[1]]
#      [,1] [,2]
# [1,]    4    6
# [2,]    5    5
# 
# [[2]]
# [,1] [,2] [,3]
# 
# [[3]]
# [,1] [,2] [,3] [,4]

【讨论】:

  • 非常好,非常感谢您的指点。所以现在我们有了给我的 target.mountain 值的掷骰子的值,我怎样才能返回“target.mountain”值(尽可能多地创建)以及骰子的其他值吨使用。理想情况下,如果剩余/未使用骰子的值不在 5:10 范围内,则将两个(如果有 2 个)骰子加在一起,这样它们就可以了。对不起,我问了这么多,我真是一无所知!
  • 我在上面更新了我的答案,这样你就可以看到你可以用剩下的骰子赚多少钱了..
  • 哇,再次感谢您。老实说,其中一些功能我什至从未听说过,但您描述得非常好。我已经在我的模型中对其进行了测试,它适用于大多数组合,只有少数几个,我将尝试根据您向我展示的内容来解决这个问题。但是非常感谢你所做的一切!当剩余的骰子总和 > 10(这是不允许的,因为它们需要在 5:10 范围内)以及目标数字出现在掷骰中 > 1 次(即 5、5、6、目标为 6 的 6 将返回 6 和 16)
  • 然后你可以在剩余的骰子上重复comboGeneral-function。因此,代替sum( vecsets::vsetdiff( Roll_dice, v) ),您执行另一个带有约束的comboGeneral。
  • 我试图改变这些,但我又遇到了一些问题(对不起!)。据我所知,您的代码组合创建 1 个 target.mountain (不考虑是否可以制作 2 个)。然后将未使用的剩余值与它们的总和相加(如果它在 5:10 范围内,这很好,但通常它更大,所以不幸的是没有用处)。你提到如果我改变 sum(....) 部分它会起作用,但我不知道如何将剩余值正确放入新的 comboGeneral 部分。但是,如果掷骰子无法创建目标值,则这些都不起作用
【解决方案2】:

这样的?

> sapply(
+   2:4,
+   function(k) combn(Roll_dice, k, sum)
+ )
[[1]]
[1] 11  9  8  8  7  5

[[2]]
[1] 14 13 11 10

[[3]]
[1] 16

或者你需要这个吗?

> lapply(
+   setNames(2:4, 2:4),
+   function(k) target.mountain %in% combn(Roll_dice, k, sum)
+ )
$`2`
[1] FALSE

$`3`
[1] TRUE

$`4`
[1] FALSE

【讨论】:

  • 太完美了!然后我将如何创建一个 if else 语句,如果 'target.mountain' 值在这些列表中的任何一个内,则执行 'something' else 'do another thing'
  • @GeorgeDunn 你想要的输出是什么?
  • 这将是变量'target.mountain',因为我有之前的代码来确定这个值。那我就想看看Roll_dice能不能创造出这个值
  • 这太好了,所以我可以通过 if(any(.....your code.....)==TRUE) 将所有这些放入 if 语句中
  • @GeorgeDunn 查看我的第二个答案。它已经完成了if 可以做的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多