在Matlab中计算具有排除准则的排列次数

Calculating number of permutations with exclusion criterion in Matlab

提问人:Rory Holden 提问时间:11/16/2023 最后编辑:DaveRory Holden 更新时间:11/17/2023 访问量:34

问:

我有一个包含 12 个项目的单词列表,由 4 个语义类别组成,每个类别有 3 个项目。这包括沙发、架子、桌子(家具)、飞机、船、卡车(车辆)、夹克、鞋子、毛衣(衣服)、生菜、胡萝卜、菠菜(蔬菜)。我需要用这 12 个项目制作一个随机列表,但是有一些规则。

首先,来自同一语义类别的项目在列表中不能相互相邻(例如生菜和菠菜)。其次,该列表分为 3 个块(第 1-4 项、第 5-8 项和第 9-12 项)。在每个块中,每个语义类别中必须至少有一个项目,但不得超过一个项目。

完整的编码菜鸟,所以我知道如何计算排列,但我不知道如何实现其他规则。任何帮助,非常感谢。

算法 数学 排列

评论

0赞 btilly 11/16/2023
我知道如何在 Python 中执行此操作,但我不知道 Matlab。你认为你可以翻译它吗?
0赞 Stef 11/16/2023
每个块有 4 个元素,正好有 4 个类别,所以“在每个块中,每个语义类别中必须至少有但不超过一个项目”只是一种复杂的方式,说“在每个块中,每个类别必须只有一个项目”。

答:

2赞 btilly 11/16/2023 #1

经过思考,我只给出伪代码。让它看起来足够像Matlab,你可能会弄清楚如何让它工作。

首先,你的单词可以排列在一个数组的数组中。喜欢这个。

word_lists = [
    ["couch", "shelf", "table"],
    ["plane", "boat", "truck"],
    ["jacket", "shoes", "sweater"],
    ["lettuce", "carrot", "spinach"]]

让我们打乱每个内部列表。我猜语法是这样的:

for i = 1:4
    word_lists[i] = word_lists[i](randperm(3))
end

现在让我们选择列表的选择。(每个列表是一个类别。

list_choices = [randperm(4), randperm(4), randperm(4)]

但可能存在一个问题。我们可能使一组中的最后一个列表选项与下一组中的第一个列表选项相同。解决这个问题。

while list_choices(1, 4) == listchoices(2, 1)
    list_choices(2) = randperm(4)
end

while list_choices(2, 4) == listchoices(3, 1)
    list_choices(3) = randperm(4)
end

现在提取您的单词列表。如果我的索引规则正确,它应该是这样的:

word_list = cat(1,
                word_lists(list_choices(1), 1),
                word_lists(list_choices(2), 2),
                word_lists(list_choices(3), 3))
0赞 Cary Swoveland 11/17/2023 #2

以下过程将生成一个满足邻接要求的列表。由于基础条件概率计算的对称性,它表示来自所有此类列表的伪随机样本。

word_lists = [
  ["couch", "shelf", "table"],
  ["plane", "boat", "truck"],
  ["jacket", "shoes", "sweater"],
  ["lettuce", "carrot", "spinach"]
]

word_lists,以及其中的每个元素(数组),当然可以是任何大小。


我们首先创建一个数组,从中保存每个类别的每个元素的类别偏移量:word_lists

[[["couch", 0], ["shelf", 0], ["table", 0]],
 [["plane", 1], ["boat", 1], ["truck", 1]],
 [["jacket", 2], ["shoes", 2], ["sweater", 2]],
 [["lettuce", 3], ["carrot", 3], ["spinach", 3]]]

接下来,可以对这个数组的每个元素(数组)进行洗牌:

[[["shelf", 0], ["table", 0], ["couch", 0]],
 [["boat", 1], ["plane", 1], ["truck", 1]],
 [["sweater", 2], ["shoes", 2], ["jacket", 2]],
 [["carrot", 3], ["spinach", 3], ["lettuce", 3]]]3

现在对这个数组进行转置:

[[["couch", 0], ["plane", 1], ["jacket", 2], ["lettuce", 3]],
 [["shelf", 0], ["boat", 1], ["shoes", 2], ["carrot", 3]], 
 [["table", 0], ["truck", 1], ["sweater", 2], ["spinach", 3]]]

接下来,对每行中的元素进行随机排序:

arr
  #=> [[["lettuce", 3], ["plane", 1], ["jacket", 2], ["couch", 0]],
  #    [["shelf", 0], ["boat", 1], ["carrot", 3], ["shoes", 2]], 
  #    [["truck", 1], ["sweater", 2], ["table", 0], ["spinach", 3]]]

如果我们在准备生成随机列表时将这个数组部分展平,我们将得到:

[["lettuce", 3], ["plane", 1], ["jacket", 2], ["couch", 0], 
 ["shelf", 0], ["boat", 1], ["carrot", 3], ["shoes", 2],
 ["truck", 1], ["sweater", 2], ["table", 0], ["spinach", 3]]

但是,这不符合要求,如下所示,两者都属于同一类别(中的偏移量)。"shelf""couch"0word_lists

我们需要先比较一下

(arr[0].last).last #=> ["couch", 0].last => 0

(arr[1].first).last #=> ["shelf", 0].last => 0

由于这些值是相同的,我们需要随机重新定位["shelf", 0]

arr[1]
  #=> [["shelf", 0], ["boat", 1], ["carrot", 3], ["shoes", 2]]

我们可以通过在 和 之间随机选择一个索引并将其插入到 元素 之后来做到这一点。假设随机索引为 。然后,我们将拥有:13arr[1][i]2

[["shelf", 0], ["boat", 1], ["carrot", 3], ["shelf", 0], ["shoes", 2]]

当然,我们必须删除这个数组的第一个元素才能得到:

[["boat", 1], ["carrot", 3], ["shelf", 0], ["shoes", 2]]

然后我们有

arr
  #=> [[["lettuce", 3], ["plane", 1], ["jacket", 2], ["couch", 0]],
  #    [["boat", 1], ["carrot", 3], ["shelf", 0], ["shoes", 2]],
  #    [["truck", 1], ["sweater", 2], ["table", 0], ["spinach", 3]]]

因为

(arr[1].last).last #=> ["shoes", 2].last #=> 2

(arr[2].first).last #=> ["truck", 1].last #=> 1

不同,无需重新定位。1["truck", 1]arr[2]

我们现在可以部分展平以获得arr

[["lettuce", 3], ["plane", 1], ["jacket", 2], ["couch", 0],
 ["shelf", 0], ["boat", 1], ["carrot", 3], ["shoes", 2],
 ["truck", 1], ["sweater", 2], ["table", 0], ["spinach", 3]]

然后将此数组的每个元素(数组)映射到该元素的第一个值中,以获得满足邻接要求的伪随机列表:

["lettuce", "plane", "jacket", "couch",
 "shelf", "boat", "carrot", "shoes",
 "truck", "sweater", "table", "spinach"]

1. 请注意,如果在上一步中 [“shelf”, 0] 被随机移动到 arr[1] 的末尾,并且 arr[2] 的第一个元素是 [“table”, 0](而不是 [“truck”, 1]),则后者必须在 arr[2] 中移动