我想得到一个多集的所有可能的分区(一个集合的不相交子集,其中并集是原始集合)(一些元素是相等的并且彼此不可区分的)。
更简单的情况是,当一个人想要产生一个简单集合的分区时,其中没有具有多重性的元素,换句话说,所有元素都是不同的。对于这个场景,我在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]]
因为集合有5个不同的分区(铃数:https://en.wikipedia.org/wiki/Bell_number)
然而,另一个集合实际上是一个multiset,它包含具有多重性的元素,那么上面的代码当然不起作用:
partitions([1,1,2]){|e| puts e.inspect}
输出:
[[1, 1, 2]]
[[1, 2], [1]] *
[[1, 2], [1]] *
[[2], [1, 1]]
[[2], [1], [1]]
可以看到两个相同的分区,用*表示,应该只产生一次。
我的问题是:如何修改
[1,2,3]
方法来处理多集,或者如何有效地过滤掉相同的分区和重复?这些相同的分割总是以连续的方式出现吗?我的目标是组织不同长宽比的图片到蒙太奇,蒙太奇的图片行将是那些设置的分区。我想最小化可能的分区中图片行之间的高度差(或等效的标准差),但是很多时候有具有相同纵横比的图片这就是我尝试处理多集的原因。
不产生一个多集的partitions而产生一个多集的powerset(所有可能的子集),通过简单的记忆过滤掉重复的:
Montage optimization by backtracking on YouTube
最佳答案
您可以将其放入数组中并使用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]]]
关于arrays - 使用Ruby产生多集的分区,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42215165/