当角色可以组合到其他角色时,如何从列表中获取所有角色组合

How to get all role combinations, from a list, when roles can be combined to other roles

上下文:考虑一个你有 N 个 6 面骰子的游戏。骰子的每一面代表一个掷骰:指挥 (COM)、科学 (SCI)、工程师 (ENG)、医疗 (MED)、安全 (SEC) 和未用于此问题的一面。游戏的目标是在挑战卡上使用骰子,其中列出了解决挑战所需的不同角色。例如,我可能有一张挑战卡,需要 1 个 COM、1 个 SCI 和 1 个 MED。所以如果我掷骰子得到1个COM、1个SCI和1个MED,我就可以将它们应用到挑战卡上来解决挑战。

附加规则:随着骰子角色映射1:1挑战卡牌要求,骰子也可以组合成变化 他们的作用如下:

  1. 2个MED可以变成1个SCI; 2 SCI 可以变成 1 MED。
  2. 2 ENG可以变成1 SEC; 2 SEC 可以变成 1 ENG.
  3. 一个COM角色+任何其他角色都可以成为任何角色。所以COM+SEC可以变成ENG.
  4. 任意三个角色都可以变成不同的角色。所以COM+SEC+ENG可以变成MED.

问题:我想为挑战卡的要求生成所有可能的骰子组合列表。例如,假设一张挑战卡需要 1 个 SCI、1 个 ENG 和 1 个 MED。手动,我看到我需要:

如果 1 个 SCI、1 个 ENG 和 1 个 MED,完成(A、B、C)
如果 1 SCI、1 ENG 和 2 SCI,完成 (A, B, D)
如果 1 SCI、1 ENG、COM 和其他,完成 (A, B, E)
if 1 SCI, 1 ENG, and 3 other, done (A, B, F)

如果 1 个 SCI、2 个 SEC 和 1 个 MED,完成(A、G、C)
如果 1 个 SCI、2 个 SCI 和 2 个 SCI,完成 (A, G, D)
if 1 SCI, 2 SEC, and COM and other, done (A, G, E)
如果 1 个 SCI、2 个 SEC 和 3 个其他,完成 (A, G, F)

如果 1 个 SCI、COM 和其他,以及 1 个 MED,完成(A、E、C)
if 1 SCI, COM and other, and 2 SCI, done (A, E, D)
if 1 SCI, COM and other, and COM and other, done (A, E, E)
如果 1 个 SCI、COM 和其他,以及 3 个其他,完成 (A, E, F)

如果 1 个 SCI、3 个其他和 1 个 MED,完成(A、F、C)
if 1 SCI, 3 other, 2 SCI, done (A, F, D)
if 1 SCI, 3 other, and COM and other, done (A, F, E)
if 1 SCI, 3 other, 3 other, done (A, F, F)

此外,我需要将最初的 1 个 SCI 替换为 2 个 MED、COM + 其他设备,以及 3 个具有相同分组的其他设备。

问题:尽管有这些例子,但我仍在努力推导出一个我可以编码的算法。有人可以提供一种算法,可以将其他角色的交换角色作为所有有效组合列表的一部分吗?

您可以将其表示为语法。您的起始状态是名义上的(直接的)挑战要求。您的边表示从该状态到另一个状态的有效过渡,每个边都显示反向过渡。

例如,对于您的卡片(SCI、ENG、MED),您将从三个元素的状态开始。您现在将包括每个转换规则可达到的状态(组合):

SCI => [MED, MED]
MED => [SCI, SCI]
b => [COM, a] for any (a, b), where a != b
d => [a, b, c] for any (a, b, c, d) where a, b, c, != d

您可以将这些规则中的每一个表达为一个函数。保留已达到的状态(组合)列表。将问题视为图遍历,并使用标准算法从给定的起始状态找到图的闭包。对于初学者:

(SCI, ENG, MED)
apply rule 1
(ENG, MED^3) push this to your `search` list
apply rule 2
(SCI^3, ENG) push this to your `search` list
apply rule 3 to "SCI"
(a, COM, ENG, MED) for all `a` != "SCI"; push these ...

看到这是怎么回事了吗?

在每次通过时,您从列表中取出第一项,根据规则对它的更改进行调整,将任何新状态推送到列表中。您需要跟踪已处理的状态,并检查每个状态中的元素数是否超过 N

你能按照那个大纲工作吗?