Here is my stab at the problem (I made it as a standalone method, as I

don't think of this operation as something that an array can do:

require 'test/unit'

def cartprod(base, *others)

return base.map{|a| [a] } if others.empty?

others = cartprod(*others)

base.inject([]) { | r, a | others.inject(r) { | r, b | r << ([a, *b]) } }

end

class CarprodTest < Test::Unit::TestCase

def test_simple

assert_equal([[1, 'a'], [1, 'b'],

[2, 'a'], [2, 'b'],

[3, 'a'], [3, 'b']],

cartprod([1,2,3], %w(a b)),

'Simple Cartesian Product failed')

assert_equal([[1, "a"], [1, "b"], [1, "c"],

[2, "a"], [2, "b"], [2, "c"],

[3, "a"], [3, "b"], [3, "c"]],

cartprod(1..3, 'a'..'c'),

'Simple Cartesian Product with ranges failed')

end

def test_multiple

assert_equal([[1, 'a', :A], [1, 'a', :B], [1, 'b', :A], [1, 'b', :B],

[2, 'a', :A], [2, 'a', :B], [2, 'b', :A], [2, 'b', :B]],

cartprod([1,2], %w(a b), [:A, :B]),

'Multiple Cartesian Product failed')

end

def test_array

assert_equal([[1, ["a", "a"]], [1, ["b", "b"]],

[2, ["a", "a"]], [2, ["b", "b"]],

[3, ["a", "a"]], [3, ["b", "b"]]],

cartprod(1..3, [%w(a a), %w(b b)]),

'Cartesian Product with arrays failed')

end

def test_base_cases

assert_equal([], cartprod([]), "Base case empty array is not correct")

assert_equal([[1], [2], [3]], cartprod(1..3), "Base case single

array is not correct")

end

end

regards,

Brian

## ···

On 11/08/05, walter a kehowski <wkehowski@cox.net> wrote:

Hello,

Since the original thread got a little long, I decided to post my next to

last version in a new thread. My previous version gave results like

[[1,4],7] for more than two arrays when you really wanted [1,4,7]. The trick

is to flatten each element of the product. The following works for any

number of arrays. Of course you might want a product in which the elements

of that product are arrays. Any suggestions?

class Array

def cartprod(b=[])

if b.empty? then

#assume self an array of arrays

inject {|cp,x| cp.cartprod(x) }

else

z = inject([]) {|a,x| b.inject(a) {|a,y| a << [x,y]}}

z.collect! {|x| x.flatten }

end

end

end

a=[1,2,3]

b=[4,5,6]

c=[7,8,9]

# works fine

p [a,b,c].cartprod

# doesn't work since [1,4,7,[10,11]] is [1,4,7,10,11]

d=[10, [11,12]]

p [a,b,c,d].cartprod

--

http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/