从概念上讲,我正在尝试从10个值的集合中构建排列的数组,例如[0-9],您可以根据排名在每个元素中选择3个值。因此,假设第一个选择的元素为0,那么下一个可能的值池将是1,2,3。如果然后选择了[0,3]三个,则下一个选择将具有[1,2,4]池,依此类推。我想要5个级别,但我当然想编写一种对级别数,值和限制条件任意的解决方案。目标是将所有排列传递回嵌套数组中。我将使用此数组来构建可视化的DataFrame。
[我的第一次尝试是使用itertools permutations
为10个值创建所有排列,然后根据与上一个条目的距离从那些不符合我的条件的排列中删除。这似乎效率低下,但我也很难确定要删除的条件。
编辑:我没有正确指定选择过程始终以[0,1,2]开始作为首选。根据每个最大级别(例如10)的下一个级别,在每个级别上添加其他选择。因此,如果在第一级别选择2,则以“ 3”代替。下一个选择是[0,1,3]。如果选择1,则您可以从下一级选择[0,3,4]。这一直持续到您达到说的5个选择的最大长度为止。
好的,如果我理解正确,这就是您要描述的过程:
Reserve: [3, 4, 5, 6, 7, 8, 9]
Pool: [0, 1, 2]
Chosen: []
只要我们还没有5个Chosen
项目,请从Pool
中删除任何项目并将其附加到所选的序列中。然后从Reserve
中删除first项并将其附加到池中。根据需要重复。
我仍然不确定这是否是您要描述的过程,因为似乎7、8和9永远不会出现在所选的顺序中,但是您确实说您正在尝试提出一个通用的解决方案,因此,我认为“预留”实际上是无限制的。
您的问题是,我们如何枚举所有可能选择的序列?
在此过程中,唯一要做的选择是从池中提取哪个元素。您总是有3个(=池的大小)选择。这些选择总是将是不同的项目(因为每个项目只有一个)。只要您确信没有两个不同的选择顺序可以产生相同的项目顺序,现在就可以看到您拥有的完全相同:
(池的大小)提高到幂(输出序列的长度)
可能的顺序。剩下的唯一棘手的事情是将选择索引序列转换为选择值序列。为了代替做任何聪明的事情,我建议简单地执行该算法。
我认为这可行。为了简化事务,而不是从池的中间删除选定的项目并从池的末尾从储备中追加新项目,我将新项目放入选定项目腾出的插槽中。这改变了我们发出序列的顺序,但是我认为它不应该改变所生成序列的整体集合。]
from itertools import (product, count) def generate_sequences(pool_size, n): for choice_sequence in product(range(pool_size), repeat=n): pool = list(range(pool_size)) sequence = [] reserve = count(pool_size) for choice_index in choice_sequence: sequence.append(pool[choice_index]) pool[choice_index] = next(reserve) yield sequence
也许有一种更简单的方法可以做到这一点,但我认为这与时间复杂度一样好。