For example, given the set
[A,B,C], I needed to calculate the following combinations:[][A][B][C][AB][AC][BC][ABC]
It dawned on me that a cool way to generate the combinations was to treat the sets (the original set and the resulting combination sets) as bit strings. If the bit corresponding to the member is on, I include the member in the combination.
To explain, I start with the set
[A,B,C]. I create a number that has three bits, all on, one for each member of the set. I therefore have the binary number 111 matching [A,B,C]. 111 happens to be 7 in decimal, which is one less than the total number of combinations I require.Starting with zero, I loop up and including seven (for a total of eight iterations, once for each combo that I want). I convert each iteration count to a binary string, which will give me which bits are on for this combination.
For example, here's the ruby code:
original_set = [:A, :B, :C]
combinations = []
def create_combo(bit_string, original_set)
combo = []
bit_string.split(//).each_with_index do |bit, i|
combo << original_set[i] if bit == "1"
end
combo
end
(2**original_set.size).times do |i|
bit_string = sprintf("%03b", i)
combinations << create_combo(bit_string, original_set)
end
require 'pp'
pp combinations
This will print out:
[[], [:C], [:B], [:B, :C], [:A], [:A, :C], [:A, :B], [:A, :B, :C]]Neat, huh?
I'm sure you can speed this up by checking each bit in the iteration count instead of first converting to a bit string.
3 comments:
This is great! I created a database of possible combinations, and just run my strings against that to get combinations.
Is it true this only works for sets with up to 9 members? I don't believe I can create a binary longer than that. Am I missing something?
[...] Semergence » Blog Archive » Calculating Combinations The Cool Way Posted in Links, Engineering || [...]
[...] started with my crazy hack to use bit strings to calculate combinations. I didn’t want to resort to creating bit strings, as I wanted to minimize the amount of work [...]
Post a Comment