Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine array of array into all possible combinations, forward only, in Ruby

I have an array of arrays, like so:

[['1','2'],['a','b'],['x','y']] 

I need to combine those arrays into a string containing all possible combinations of all three sets, forward only. I have seen lots of examples of all possible combinations of the sets in any order, that is not what I want. For example, I do not want any of the elements in the first set to come after the second set, or any in the third set to come before the first, or second, and so on. So, for the above example, the output would be:

['1ax', '1ay', '1bx', '1by', '2ax', '2ay', '2bx', '2by'] 

The number of arrays, and length of each set is dynamic.

Does anybody know how to solve this in Ruby?

like image 909
Travis Avatar asked Mar 08 '11 00:03

Travis


2 Answers

Know your Array#product:

a = [['1','2'],['a','b'],['x','y']] a.first.product(*a[1..-1]).map(&:join) 
like image 141
Andrew Grimm Avatar answered Sep 30 '22 09:09

Andrew Grimm


Solved using a recursive, so-called "Dynamic Programming" approach:

  • For n-arrays, combine the entries of the first array with each result on the remaining (n-1) arrays
  • For a single array, the answer is just that array

In code:

def variations(a)   first = a.first   if a.length==1 then     first   else     rest = variations(a[1..-1])     first.map{ |x| rest.map{ |y| "#{x}#{y}" } }.flatten   end end  p variations([['1','2'],['a','b'],['x','y']]) #=> ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"]  puts variations([%w[a b],%w[M N],['-'],%w[x y z],%w[0 1 2]]).join(' ') #=> aM-x0 aM-x1 aM-x2 aM-y0 aM-y1 aM-y2 aM-z0 aM-z1 aM-z2 aN-x0 aN-x1 aN-x2 #=> aN-y0 aN-y1 aN-y2 aN-z0 aN-z1 aN-z2 bM-x0 bM-x1 bM-x2 bM-y0 bM-y1 bM-y2 #=> bM-z0 bM-z1 bM-z2 bN-x0 bN-x1 bN-x2 bN-y0 bN-y1 bN-y2 bN-z0 bN-z1 bN-z2 

You could also reverse the logic, and with care you should be able to implement this non-recursively. But the recursive answer is rather straightforward. :)

like image 40
Phrogz Avatar answered Sep 30 '22 09:09

Phrogz