我想基于数字的起始列表有效地生成唯一的数字组合列表。
示例启动list = [1,2,3,4,5]
但该算法适用于[1,2,3...n]
result =
[1],[2],[3],[4],[5]
[1,2],[1,3],[1,4],[1,5]
[1,2,3],[1,2,4],[1,2,5]
[1,3,4],[1,3,5],[1,4,5]
[2,3],[2,4],[2,5]
[2,3,4],[2,3,5]
[3,4],[3,5]
[3,4,5]
[4,5]
请注意。我不想要重复组合,虽然我可以使用它们,例如在上面的例子中我并不需要组合[1,3,2],因为它已经作为[1,2,3]
答案 0 :(得分:63)
只需将0
计算到2^n - 1
,然后根据计数的二进制表示打印数字。 1
表示您打印该号码,0
表示您不打印。例如:
set is {1, 2, 3, 4, 5}
count from 0 to 31:
count = 00000 => print {}
count = 00001 => print {1} (or 5, the order in which you do it really shouldn't matter)
count = 00010 => print {2}
00011 => print {1, 2}
00100 => print {3}
00101 => print {1, 3}
00110 => print {2, 3}
00111 => print {1, 2, 3}
...
11111 => print {1, 2, 3, 4, 5}
答案 1 :(得分:19)
你要问的是一个名字。它被称为power set。
Google搜索“power set algorithm”让我看到了recursive solution。
def powerset!(set)
return [set] if set.empty?
p = set.pop
subset = powerset!(set)
subset | subset.map { |x| x | [p] }
end
如果S =(a,b,c)则 powerset (S)是所有子集的集合 powerset (S)= {(),(a),(b),(c),(a,b),(a,c),(b,c),(a,b ,C)}
第一个“技巧”是尝试递归定义。
什么是停止状态?
S =()有什么 powerset (S)?
如何呢?
通过一个元素减少设置
考虑取出一个元素 - 在上面的例子中,取出{c}
S =(a,b)然后 powerset (S)= {(),(a),(b),(a,b)}
缺少什么?
powerset (S)= {(c),(a,c),(b,c),(a,b,c)}
嗯
请注意任何相似之处?再看看......
powerset (S)= {(),(a),(b),(c),(a,b),(a,c),(b,c),( A,b,C)}
取出任何元素
powerset (S)= {(),(a),(b),(c),(a,b),(a,c),(b,c),( a,b,c)} 是
powerset (S - {c})= {(),(a),(b),(a,b)}与
联合{c} U powerset (S - {c})= {(c),(a,c),(b,c),(a,b,c)}
powerset (S)= powerset (S - {e i })U({e i } U powerset (S - {e i }))
其中e i 是S(单身)的元素
答案 2 :(得分:5)
def power(a)
(0..a.size).map {|x| a.combination(x).to_a}.flatten(1)
end
答案 3 :(得分:0)
与hobodave的答案相同,但迭代且更快(在Ruby中)。它也适用于Array
和Set
。
def Powerset(set)
ret = set.class[set.class[]]
set.each do |s|
deepcopy = ret.map { |x| set.class.new(x) }
deepcopy.map { |r| r << s }
ret = ret + deepcopy
end
return ret
end
在我的测试中,IVlad的方法在Ruby中运行得不好。
答案 4 :(得分:0)
来自OP的评论(复制编辑):
这个例子是我实际做的简化形式。数字是具有属性“数量”的对象,我想对每个可能组合的数量求和,然后选择使用最多对象的组合,其中数量
N
的总和在其他边界内,例如x < N < y
。
您拥有的是优化问题。您所假设的是,解决此优化问题的正确方法是将其分解为枚举问题(这是您所要求的),然后是过滤问题(可能您知道该怎么做)。
你还没有意识到这种解决方案只能用于(a)理论分析,或(b)非常小的n
值。你要求的枚举在n
中是指数式的,这意味着你最终会得到一些在实践中运行时间太长的东西。
因此,弄清楚如何摆出优化问题,编写一个新问题,并编辑一个问题指向它。
答案 5 :(得分:0)
用于计算方案中的功率集的递归和迭代解决方案。尚未完全测试
(define (power_set set)
(cond
((empty? set) (list '()))
(else
(let ((part_res (power_set (cdr set))))
(append (map (lambda (s) (cons (car set) s)) part_res) part_res)))))
(define (power_set_iter set)
(let loop ((res '(())) (s set))
(if (empty? s)
res
(loop (append (map (lambda (i) (cons (car s) i)) res) res) (cdr s)))))
答案 6 :(得分:0)
此后是递归解决方案,类似于已发布的解决方案。一些断言提供了一种单元测试。 我没有设法使用“set”Python类型来表示集合。 Python在尝试像“s.add(set())”这样的表达时说“设置对象是不可用的”。
请参阅http://rosettacode.org/wiki/Power_set
中许多编程语言的解决方案def generatePowerSet(s, niceSorting = True):
"""Generate power set of a given set.
The given set, as well as, return set of sets, are implemented
as lists.
"niceSorting" optionnaly sorts the powerset by increasing subset size.
"""
import copy
def setCmp(a,b):
"""Compare two sets (implemented as lists) for nice sorting"""
if len(a) < len(b):
return -1
elif len(a) > len(b):
return 1
else:
if len(a) == 0:
return 0
else:
if a < b:
return -1
elif a > b:
return 1
else:
return 0
# Initialize the power set "ps" of set "s" as an empty set
ps = list()
if len(s) == 0:
ps.append(list())
else:
# Generate "psx": the power set of "sx",
# which is "s" without a chosen element "x"
sx = copy.copy(s)
x = sx.pop()
psx = generatePowerSet(sx, False)
# Include "psx" to "ps"
ps.extend(psx)
# Include to "ps" any set, which contains "x"
# Such included sets are obtained by adding "x" to any subset of "sx"
for y in psx:
yx = copy.copy(y)
yx.append(x)
ps.append(yx)
if niceSorting:
ps.sort(cmp=setCmp)
return ps
assert generatePowerSet([]) == [[]]
assert generatePowerSet(['a']) == [[], ['a']]
assert generatePowerSet(['a', 'b']) == [[], ['a'], ['b'], ['a', 'b']]
assert generatePowerSet(['a', 'b','c']) == [[],
['a'], ['b'], ['c'],
['a', 'b'], ['a', 'c'], ['b', 'c'],
['a', 'b', 'c'] ]
assert generatePowerSet(['a', 'b','c'], False) == [ [],
['a'],
['b'],
['a', 'b'],
['c'],
['a', 'c'],
['b', 'c'],
['a', 'b', 'c'] ]
print generatePowerSet(range(4), True)
答案 7 :(得分:0)
我的同事创造了一种优雅的红宝石制作方式。它在索引集上使用了IVlad的概念。
class Array
def select_by_index(&block)
# selects array element by index property
n = []
each_with_index do |e, i|
if block.call(i)
n << e
end
end
n
end
end
def pow(a)
# power set of a
max = (1 << a.length)
(0...max).map { |i| a.select_by_index { |k| (1 << k) & i != 0 }}
end