Dan Jameson
Dan Jameson

Reputation: 1520

In Ruby, how can I iterate over an arbitrary number of arrays?

I am doing something very much like the knapsack problem, in which I want to iterate over all combinations of an arbitrary number of inputs.

For example, if my function takes 3 arrays, I want to get all i×j×k combinations. If my function takes 5 arrays, I want to get all i×j×k×l×m combinations.

Example one:

result = all_products([1,2,3,4,5], [1,2,3], [10,20,30,40,50,60,70,80])

result.length == 120

Example two:

result = all_products([1,2,3], [1,2,3], [1,2,3], [1,2,3], [1,2,3], [1,2,3])

result.length == 729

But I don't know how many arrays I am going to take in.

What's the way to do this in Ruby?

This is NOT asking how to find all pairs of 1 array. My input arrays will likely all be different.

Here is what I tried so far:

def self.all_combinations(*sets)
 input = *sets; 
 prod = sets.inject(1) { |p,a| p * a.length } 
 prod.times do |p| 
  args = [] 
  index = p 
  input.each do |array| 
    quotient = index / array.length
    remainder = index % array.length
    args << array[remainder] 
    index = quotient
    pp args 
  end 
end 

Upvotes: 1

Views: 171

Answers (1)

Marc Rohloff
Marc Rohloff

Reputation: 1352

I would start off with getting the 'product' of 2 arrays:

def product2(array1, array2)
  array1.map { |e1| array2.map { |e2| e1*e2 } }.flatten
end

You can then generalize to any number of arrays:

def all_products(*arrays)
  arrays.reduce([1]) { |result, array| product2(result, array) }
end

You might want to handle corner cases (for example empty arrays or no input arrays at all)

Upvotes: 1

Related Questions