
class Array

  # The array is expected to be and array of arrays, which
  # iterates through combinations of each in position.
  #
  #   a = [ [0,1], [2,3] ]
  #   a.each_combo { |c| p c }
  #
  # produces
  #
  #   [0, 2]
  #   [0, 3]
  #   [1, 2]
  #   [1, 3]
  #

  def each_combo
    a = collect{ |x|
      x.respond_to?(:to_a) ? x.to_a : 0..x
    }

    if a.size == 1
      r = a.shift
      r.each{ |n|
        yield n
      }
    else
      r = a.shift
      r.each{ |n|
        a.each_combo{ |s|
          yield [n, *s]
        }
      }
    end
  end


  # As with each_combo but returns combos collected in an array.

  def combos
    a = []
    each_combo{ |c| a << c }
    a
  end

end

