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

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


Know your Array#product:

a = [['1','2'],['a','b'],['x','y']]a.first.product(*a[1..-1]).map(&:join)


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  endendp 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. :)


Pure, reduce with product:

a = [['1','2'],['a','b'],['x','y']]a.reduce() { |acc, n| acc.product(n).map(&:flatten) }.map(&:join)#  => ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"]