From: Srinivas Jonnalagadda Date: 2006-01-16T14:12:00+09:00 Subject: Generating combinations from multiple sets Dear all, I have a requirement as below. There are 'n' containers of lengths {l_i}, i = 1,..,n. All these containers are collected into an array. Picking one element at a time from each container, an array has to be constructed and either yielded or accumulated. I have written the following code that seems to work reasonably. Are there simpler or more efficient ways of doing this? Thanks in advance, JS * * * * def generate_combinations(cont_ary, &blk) cont_count = cont_ary.length return if cont_count < 1 if cont_count == 1 if block_given? cont_ary[0].each { | el | yield [el] } return else return cont_ary[0].collect { | el | [el] } end end cur_indices = Array.new(cont_count, 0) combinations = [] generate_combinations_iterator(cont_ary, 0, cur_indices, :working_set => Array.new(cont_count), :accumulator => combinations, &blk) return combinations unless block_given? end # def generate_combinations_iterator(cont_ary, cur_cont, cur_indices, opts = {}, &blk) cont_ary[cur_cont].each_with_index do | el, i | opts[:working_set][cur_cont] = el case cur_cont when 0 cur_indices[cur_cont] = i (1...cur_indices.length).each { | j | cur_indices[j] = 0 } generate_combinations_iterator(cont_ary, cur_cont + 1, cur_indices, opts, &blk) when cont_ary.length-1 if block_given? yield opts[:working_set] else opts[:accumulator] << Array.new(opts[:working_set]) end else cur_indices[cur_cont] = i generate_combinations_iterator(cont_ary, cur_cont + 1, cur_indices, opts, &blk) end end end # Output ------ irb(main):011:0> load 'combination-generator.rb' => true irb(main):012:0> ary1 = [] => [] irb(main):013:0> generate_combinations(ary1) => nil irb(main):014:0> ary2 = [[1, 2, 3, 4]] => [[1, 2, 3, 4]] irb(main):015:0> pp generate_combinations(ary2) [[1], [2], [3], [4]] => nil irb(main):016:0> ary3 = [[1, 2, 3, 4], ['a', 'b', 'c']] => [[1, 2, 3, 4], ["a", "b", "c"]] irb(main):017:0> pp generate_combinations(ary3) [[1, "a"], [1, "b"], [1, "c"], [2, "a"], [2, "b"], [2, "c"], [3, "a"], [3, "b"], [3, "c"], [4, "a"], [4, "b"], [4, "c"]] => nil