我想获得multiset的所有可能的分区(一个集合的不相交的子集,其中union是原始集合)(一些元素是相同的并且彼此不可区分)。
更简单的情况是,人们想要产生一个简单集的分区,其中没有具有多重性的元素,换句话说,所有元素都是不同的。对于这种情况,我在StackOwerflow上发现了这个Ruby代码非常有效,因为它不存储所有可能的分区,而是将它们生成块:
def partitions(set)
yield [] if set.empty?
(0 ... 2 ** set.size / 2).each do |i|
parts = [[], []]
set.each do |item|
parts[i & 1] << item
i >>= 1
end
partitions(parts[1]) do |b|
result = [parts[0]] + b
result = result.reject do |e|
e.empty?
end
yield result
end
end
end
示例:
partitions([1,2,3]){|e| puts e.inspect}
输出:
[[1, 2, 3]]
[[2, 3], [1]]
[[1, 3], [2]]
[[3], [1, 2]]
[[3], [2], [1]]
由于集[1,2,3]
有5种不同的分区(无论如何都是贝尔数:https://en.wikipedia.org/wiki/Bell_number)
然而,实际上是多重集的另一个集包含具有多重性的元素,那么上面的代码当然不起作用:
partitions([1,1,2]){|e| puts e.inspect}
输出:
[[1, 1, 2]]
[[1, 2], [1]] *
[[1, 2], [1]] *
[[2], [1, 1]]
[[2], [1], [1]]
可以看到两个相同的分区,用*表示,应该只产生一次。
我的问题是:我如何修改def partitions()
方法以使用多重集合,或者如何以有效的方式过滤掉相同的分区,重复?那些相同的分区是否总是以连续的方式相互跟随?
我的目标是将具有不同宽高比的图像组织成蒙太奇,蒙太奇的图片行将是那些设置的分区。我想在可能的分区中最小化图片行之间的高度差异(或等效的标准偏差),但很多时候有相同宽高比的图片,这就是我尝试处理多重集合的原因。
不是分区而是多重集的powersets(所有可能的子集),通过简单的memoization过滤掉重复项:
答案 0 :(得分:2)
您可以将其放入数组并使用uniq
:
arr = []
partitions([1,1,2]) { |e| arr << e }
puts arr.to_s
#-> [[[1, 1, 2]], [[1, 2], [1]], [[1, 2], [1]], [[2], [1, 1]], [[2], [1], [1]]]
puts arr.uniq.to_s
#-> [[[1, 1, 2]], [[1, 2], [1]], [[2], [1, 1]], [[2], [1], [1]]]