Python 生成生成生成集的算法
给定此输入:[1,2,3,4] 我想生成生成集:Python 生成生成生成集的算法,python,algorithm,Python,Algorithm,给定此输入:[1,2,3,4] 我想生成生成集: [1] [2] [3] [4] [1] [2] [3,4] [1] [2,3] [4] [1] [3] [2,4] [1,2] [3] [4] [1,3] [2] [4] [1,4] [2] [3] [1,2] [3,4] [1,3] [2,4] [1,4] [2,3] [1,2,3] [4] [1,2,4] [3] [1,3,4] [2] [2,3,4] [1] [1,2,3,4] 每个集合都有原始集合的所有元素,它们排列成唯一的子集。产生这
[1] [2] [3] [4]
[1] [2] [3,4]
[1] [2,3] [4]
[1] [3] [2,4]
[1,2] [3] [4]
[1,3] [2] [4]
[1,4] [2] [3]
[1,2] [3,4]
[1,3] [2,4]
[1,4] [2,3]
[1,2,3] [4]
[1,2,4] [3]
[1,3,4] [2]
[2,3,4] [1]
[1,2,3,4]
每个集合都有原始集合的所有元素,它们排列成唯一的子集。产生这些集合的算法是什么?我尝试过使用choose、permutation、combination、powerset等Python生成器函数,但无法获得正确的组合
2009年1月20日
这不是一个家庭作业问题。这是我为www.projecteuler.net问题118所做的改进答案。我已经有了一个缓慢的解决方案,但找到了一个更好的方法——除了我不知道如何生成集
当我从一个就职聚会回来的时候,我会把我的密码贴出来
2009年1月21日
这是我最终使用的算法:
def spanningsets(items):
if len(items) == 1:
yield [items]
else:
left_set, last = items[:-1], [items[-1]]
for cc in spanningsets(left_set):
yield cc + [last]
for i,elem in enumerate(cc):
yield cc[:i] + [elem + last] + cc[i+1:]
@尤瓦尔F:我知道怎么做动力装置。下面是一个简单的实现:
def powerset(s) :
length = len(s)
for i in xrange(0, 2**length) :
yield [c for j, c in enumerate(s) if (1 << j) & i]
return
def动力装置:
长度=长度(s)
对于X范围内的i(0,2**长度):
yield[c代表j,c在枚举(s)中,如果(1这是怎么回事?我还没有测试它,但我稍后会尝试
我认为这种技术叫做动态规划:
取第一个元素[1]
您可以用它创建什么?只有[1]
拿第二个[2]
现在有两种可能性:[1,2]
和[1][2]
拿第三个[3]
使用数字2的第一个[1,2]
可以创建[1,2,3]
和[1,2][3]
使用数字2的第二个[1][2]
可以创建[1,3][2]
和[1][2,3]
和[1][2][3]
我希望我试图展示的内容足够清晰。(如果没有,请发表评论!)这应该可以,尽管我还没有对它进行足够的测试
def spanningsets(items):
if not items: return
if len(items) == 1:
yield [[items[-1]]]
else:
for cc in spanningsets(items[:-1]):
yield cc + [[items[-1]]]
for i in range(len(cc)):
yield cc[:i] + [cc[i] + [items[-1]]] + cc[i+1:]
for sset in spanningsets([1, 2, 3, 4]):
print ' '.join(map(str, sset))
输出:
[1] [2] [3] [4]
[1, 4] [2] [3]
[1] [2, 4] [3]
[1] [2] [3, 4]
[1, 3] [2] [4]
[1, 3, 4] [2]
[1, 3] [2, 4]
[1] [2, 3] [4]
[1, 4] [2, 3]
[1] [2, 3, 4]
[1, 2] [3] [4]
[1, 2, 4] [3]
[1, 2] [3, 4]
[1, 2, 3] [4]
[1, 2, 3, 4]
下面是关于这个问题的一页。也许您可以将其中一个代码引用翻译成python
编辑:这是一个类似的问题。是关于生成分区的SUNY repository页面,我认为这是正确的问题。结果集和空集{}看起来像是(或幂集)的结果,但不是同一件事
我写了一篇关于类似问题的文章,这个问题有一些实现(虽然是C#),在某些情况下更注重速度而不是清晰度。第一个例子应该很容易翻译。也许它会给出一些想法
它们的工作原理是,对组合进行emumerating类似于二进制计数(想象从0到16计数)。您不说明顺序是否重要,也不只是生成所有组合,因此之后可能需要进行快速整理
这里有一个(忽略这个奇怪的标题,讨论的方向是另一个)我认为下面的方法是生成euler问题的最佳方法,因为你可以用素数生成子集的数量来替换返回值,而乘法(尤其是记忆法)是很简单的:
关键部分是确保递归端始终具有最左边的元素,这样就不会得到重复的元素
我有一些乱七八糟的C#代码:
IEnumerable<IEnumerable<List<int>>> GenerateSubsets(List<int> list)
{
int p = (1 << (list.Count)) - 2;
List<int> lhs = new List<int>();
List<int> rhs = new List<int>();
while (p >= 0)
{
for (int i = 0; i < list.Count; i++)
if ((p & (1 << i)) == 0)
lhs.Add(list[i]);
else
rhs.Add(list[i]);
if (rhs.Count > 0)
foreach (var rhsSubset in GenerateSubsets(rhs))
yield return Combine(lhs, rhsSubset);
else
yield return Combine(lhs, null);
lhs.Clear();
rhs.Clear();
p -= 2;
}
}
IEnumerable<List<int>> Combine(List<int> list, IEnumerable<List<int>> rest)
{
yield return list;
if (rest != null)
foreach (List<int> x in rest)
yield return x;
}
IEnumerable生成子集(列表)
{
int p=(1=0)
{
for(int i=0;i
对于haskell和ruby来说,这也是一个很好的问题,对于清晰的示例+1。每个步骤的一般规则是“将元素放入一个现有子集中,或放入一个新的子集中”。这很清楚,但只是为了记录,它不是动态编程。DP是指采用缓慢(如指数时间)的递归算法和记录(“备忘录”)部分解决方案,以便可重复使用,从而实现更快的解决方案(例如O(n^2))算法。如果你为问题的最小子集创建解决方案,那么动态规划不就是问题的第二个最小子集吗?gs:哎呀,我说得太快了。是的,如果你重用通过解决较小的子问题生成的子集,而不是重新生成它们,那就是DP。我很高兴知道我还没有完成你误解了DP:)+1:参考已知正确且完整的算法。这是相关的,但不是同一个问题。幂集不是问题的答案。已编辑。只是出于兴趣,生成集和幂集之间有什么区别?示例的结果将是相同的,不是吗?我知道这并不意味着ut会对所有例子都适用。幂集是所有子集的集。生成集的每个成员都是一组集,其并集是原始集。例如,{1,2,3}的幂集是{{},{1},{2},{1,2},{3},{1,3},{2,3}。功率集中始终有2^n个集合,因为集合中的n个基本元素中的每一个都可以存在或不存在,就像n位字中的每一位都可以打开或关闭一样。第4行可以是:yield[项目]这是一个非常奇怪的生成器函数。我从来没有见过一个在外循环中有递归的函数,也没有见过一个在else stmt中有两个收益率的函数。我肯定要仔细考虑一下。感谢一个伟大的解决方案!@recursive:最初是这样的。我将它改为yield[[items[-1]]
强调循环内收益率的相似性。顺便说一下,我认为最好只传递初始列表中的位置,而不是传递列表的整个部分spanningset(items[:-1]) IEnumerable<IEnumerable<List<int>>> GenerateSubsets(List<int> list)
{
int p = (1 << (list.Count)) - 2;
List<int> lhs = new List<int>();
List<int> rhs = new List<int>();
while (p >= 0)
{
for (int i = 0; i < list.Count; i++)
if ((p & (1 << i)) == 0)
lhs.Add(list[i]);
else
rhs.Add(list[i]);
if (rhs.Count > 0)
foreach (var rhsSubset in GenerateSubsets(rhs))
yield return Combine(lhs, rhsSubset);
else
yield return Combine(lhs, null);
lhs.Clear();
rhs.Clear();
p -= 2;
}
}
IEnumerable<List<int>> Combine(List<int> list, IEnumerable<List<int>> rest)
{
yield return list;
if (rest != null)
foreach (List<int> x in rest)
yield return x;
}