返回从不同箱中取出的 n 个对象的所有可能组合的算法
为了使其更具体,我需要一个算法(无论是否递归),给定一个整数 n 和一个矩阵作为输入,该算法将返回所有具有以下组合的组合: 1) 每行至少 1 个对象 2)总共有n个对象
我觉得如果我尝试所有组合并使用每行有n个对象和1个对象的组合,我觉得我可以更容易地解决这个问题,但我相信该算法可以比这更有效。 我还成功地编写了一种算法,该算法将返回每行 1 个对象的所有组合,但无法将其扩展为更多。我一直用 Python 编码,但任何语言都可以。需要额外考虑的是,python 按引用传递对象。 =)
假设矩阵是平方的。如果有人想知道为什么,这是我试图解决的更复杂的图形算法的一部分。
谢谢大家!
To make it more specific, I need an algorithm (recursive or not) that, given a integer n and a matrix as input, will return me all of the combinations that will have:
1) At least 1 object from each line
2) Will have n objects total
I feel I could solve this easier if I just tried all combinations and use the ones that have n objects and 1 from each line, but I believe that the algorithm can be a lot more efficient than that.
I have also successfully coded an algorithm that will return all combinations of 1 object per line, but couldn't expand it to more. I've been coding in Python, but any language is fine. Extra points for consideration that python passes objects per reference. =)
Assume the matrix is squared. If anyone wants to know why, this is part of a more complex graph algorithm I'm trying to solve.
Thanks all!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
假设矩阵
m
是一个列表的列表;这是一个 Racket 函数:Assume the matrix
m
is a list of lists; here is a Racket function for it:感谢所有的答案,它们很接近我正在寻找的东西。我设法在Python下完成它(所以我没有检查这里发布的结果),我的问题实际上是Python在函数调用中传递引用与复制。我认为浅拷贝就足够了,但显然我需要一个深拷贝(没有想过为什么浅拷贝还不够)。
我就是这样做的:
PS1:这里的图表是列表的字典。 n_edges 是要从图中选取的边数
PS2:这里的大小计算效率很低,还没有花时间修复它。
PS3:为了在字典上有序迭代,我创建了两个列表:图形的列表列表表示(lol)和与其匹配的索引数组(lolindex)。
PS4:适应我发布的问题,我使用的真实方法有更多问题特定的代码。还没有按照我在这里放置的方式测试代码。
Thanks for all the answers, they were close to what I was looking for. I managed to do it under Python (so I didn't check the results posted here), my problem was actually Python passing reference vs copy in function calls. I thought a shallow copy would have been enough, but apparently I needed a deep copy (haven't thought it through why shallow wasn't enough).
This is how I did it:
PS1: Graphs here are dictionaries of lists. n_edges is the number of edges to be picked from the graph
PS2: Size calculation here is pretty inefficient, haven't taken time to fix it yet.
PS3: In order to iterate orderly over a dictionary, I created two lists: a list-of-lists representation of the graph (lol) and an index array that matches it (lolindex).
PS4: Adapted to fit the question I posted, the real method I used has more problem specific code to it. Haven't tested the code in the way I put it here.
您很可能想修改任务并列出简单列表的所有组合?
下面是一个 Javascript 函数,可以为您完成此操作:
Most likely you want to modify the task and list all combinations of a simple list?
Below is a Javascript function that will do this for you:
多么好的问题啊!为了与术语保持一致,我将矩阵中的行称为“输入 bags” 和输入袋中的物品作为“对象”。包(或多集)是一个容器,允许成员多次出现,但其成员没有固有的顺序(与列表不同)。
我们正在寻找具有以下签名的函数:
由于有效组合集可能超出 Python 可用的内存,因此
generate_combinations
应返回一个生成器而不是显式列表。有效结果必须满足以下要求:
我假设以下内容:
要求 #1 和假设 #4 意味着输入袋的数量
n <= 中的对象总数所有包
数据结构
我将使用 Python 的内置
itertools
模块来生成组合,该模块是在 v2.6 中引入的。如果您运行的是旧版本的 Python,请使用配方。对于这些代码示例,为了清楚起见,我已将生成器隐式转换为列表。意识到上述问题可以简化为可以通过 Python 内置的 itertools 模块立即解决的问题,该模块生成序列的组合。我们需要做的唯一修改是消除要求#1。为了解决减少的问题,请将袋子的成员组合成一个袋子。
为了恢复要求#1,每个有效组合(输出包)需要包含来自每个输入包的 1 个元素以及来自任何包的附加元素,直到输出包大小达到用户指定的值。如果忽略[每个输入袋中的 1 个元素]和[任何袋中的附加元素]之间的重叠,则解决方案只是第一个可能的组合和第二个可能的组合的笛卡尔积。
要处理重叠,请从 [来自任何包的附加元素] 中删除 [每个输入包中的 1 个元素] 中的元素,然后进行 for 循环。
列表支持删除操作,但生成器不支持删除操作。为了避免将 all_objects 作为列表存储在内存中,请创建一个跳过 base_combo 中的元素的函数。
Bag 类的实现可能如下所示:
完整代码
通过添加错误检查代码(例如 output_bag_size >= len(input_bags))来完成此操作。
这种方法的好处是:
1. 需要维护的代码更少(即itertools)
2.无递归。 Python 性能随着调用堆栈高度的增加而降低,因此最小化递归是有益的。
3. 最小的内存消耗。该算法需要超出输入包列表消耗的恒定空间内存。
What a great question! To be consistent with terminology, I will refer to the lines in your matrix as "input bags" and the items in the input bags as "objects". A bag (or multiset) is a container that allow members to appear more than once but whose members do not have an inherent order (unlike lists).
We are looking for a function with the following signature:
Since it is possible that the set of valid combinations exceeds the memory available to Python,
generate_combinations
should return a generator rather than an explicit list.A valid result must satisfy the following requirements:
I am assuming the following:
Requirement #1 and Assumption #4 imply
number of input bags <= n <= total number of objects in all bags
Data Structures
I will use Python's built-in
itertools
module to generate combinations, which was introduced in v2.6. If you are running an older version of Python, use a recipe. For these code-examples, I have implicitly converted generators into lists for clarity.Realize that the problem as stated above can be reduced to one that is immediately solvable by Python's built-in itertools module, which generates combinations of sequences. The only modification we need to do is eliminate Requirement #1. To solve the reduced problems, combine the members of the bags into a single bag.
To reinstate requirement #1, each valid combination (output bag) needs to contain 1 element from each input bag plus additional elements from any of the bags until the output bag size reaches the user-specified value. If the overlap between [1 element from each input bag] and [additional elements from any of the bags] is ignored, the solution is just the cartesian product of the possible combinations of the first and the possible combinations of the second.
To handle the overlap, remove the elements from [1 element from each input bag] from the [additional elements from any of the bags], and for-loop away.
The remove operation is supported on lists but isn't supported on generators. To avoid storing all_objects in memory as a list, create a function that skips over the elements in base_combo.
An implementation of the Bag class might look like this:
Complete code
Finish this off by adding in error-checking code (such as output_bag_size >= len(input_bags).
The benefits of this approach are:
1. Less code to maintain (namely itertools)
2. No recursion. Python performance degrades with call stack height, so minimizing recursion is beneficial.
3. Minimum memory consumption. This algorithm requires constant-space memory beyond what's consumed by the list of input bags.