Hello, How would I create a function that will take list (array) of integers and return their cartesian product? Thank You, Walter Kehowski nuby
Hello, How would I create a function that will take list (array) of integers and return their cartesian product? Thank You, Walter Kehowski nuby
> How would I create a function that will take list (array) of integers and You could do something like: a = [1, 2, 3] b = [] a.each do |elementone| a.each do |elementtwo| b << [elementone, elementtwo] end end That should do the trick (I haven't tested it though)
Giovanni, Yes, that works. Another nuby question: How to make it a function? Such as cartprod(a,b) returning c? Walter
Remember that in Ruby you seldom have standalone functions. You should probably create a class that has the cartprod method. Giovanni, Here's what I have so far: def cartprod(a,b) c=[] a.each do |ae| b.each do |be| c << [ae, be] end end return c end a=[1,2,3] b=[4,5,6] c=cartprod(a,b) c.each { |ce| print ce,"\n" } and this does print all the elements of c. Great. Now how do I do a class? Can I create a new method for Array? Walter Kehowski
Remember that in Ruby you seldom have standalone functions. You should probably create a class that has the cartprod method.
class Array def cartprod(b) c=[] each do |ae| b.each do |be| c << [ae, be] end end c end end a=[1,2,3] b=[4,5,6] c = a.cartprod(b) c.each { |ce| p ce } daz
if you want to create a new method for array just do class Array def cartprod(ary) result = [] self.each do |ae| ary.each do |be| result << [ae, be] end end result end end this way you can have an array and do new_array = source_array.cartprod(other_array)
Note that it might be more memory efficient to write a iteration method: def cartprod(a,b) a.each {|ae| b.each {|be| yield ae, be}} end Then you can also do this if needed c=[] cartprod(a,b) {|x,y| c << [x,y]} If you just need every combination once the iteration approach is more efficient. Kind regards robert
Or even better, if block_given? yield ae, be else (c ||= []) << ae, be end martin
I'm sure you know what you're talking about, but I wonder how many others will, even with comments. (Maybe I just need to go back to Pascal?) Randy Kramer
Haha... if it's this line you have trouble with (c ||= []) << ae, be it's not that hard. The ||= is a well-known idiom -- same as c = c || [] here. Basically "assign c this value, unless it is already non-nil." So then you have either an existing array or an empty one. Then you can append (<<) onto it. If it's the yield that bothers you, just study a bit more Ruby. Pascal was wonderful in 1980 -- unless you already knew something better -- but I'm content to let it go now. ;) Hal
Hal, Thanks--that line was the most confusing. (Yield I at least have a clue about, though I would need to think about it in this context a little more.) regards, Randy Kramer
Hello, Here's what I have so far, combining the previous suggestions of Robert Klemme and Martin DeMello: class Array def cartprod(a,b) a.each {|ae| b.each {|be| if block_given? yield ae,be else (c ||= []) << ae,be end end end #Array However, c=cartprod([1,2,3],[4,5,6]) c.each { |ce| print ce,"\n" } gives the following syntax error: cartprod.rb:24: syntax error (c ||= []) << ae,be ^ cartprod.rb:26: syntax error cartprod.rb:132: syntax error and I would like to take the cartesian product of an arbitrary number of sets in the most elegant way.
Hello, The following is not in the spirit of previous comments class Array def cartprod(b) c=[] each {|ae| b.each {|be| c << [ae, be] } } c.collect! {|ce| ce.flatten} end #cartprod end #Array a=[[1,2,3],[4,5,6],[7,8,9]] c=a[0] as=a.slice(1..a.length-1) as.each {|ase| c=c.cartprod(ase) } c.each {|ce| ce.each {|x| print x," " }; print "\n" } Would the following be desirable? If cartprod has two or more arguments, do the usual thing, but if it has just one, it takes the cartesian product with that argument, i.e, cartprod(a) gives cartprod(a,a) or a.cartprod(a), etc. And thanks for all the suggestion so far. I usually just play around with Perl but got $#@% fatigue. It was a toss-up between Python and Ruby so here I am. Walter Kehowski
walter a kehowski wrote... class Array def cartprod(b) each do |ae| b.each do |be| if block_given? yield ae, be # <-- you can yield multiple objects else (c ||= []) << [ae, be] # <-- you need to put (ae, be) in a single # object (i.e. an array) to put in an array end end # <-- you had missed 2 closing braces (line 132 error) end c # <-- you want to return this if no block was given end end Cheers, Dave
Hello, did I miss some standard library function? Anyway, then I'll do it on my own: def cartprod(*args) result = [[]] while [] != args t, result = result, [] b, *args = args t.each do |a| b.each do |n| result << a + [n] end end end result end Example: cartprod([1,2],[3,4,5],[6,7,8]) => [[1, 3, 6], [1, 3, 7], [1, 3, 8], [1, 4, 6], [1, 4, 7], [1, 4, 8], [1, 5, 6], [1, 5, 7], [1, 5, 8], [2, 3, 6], [2, 3, 7], [2, 3, 8], [2, 4, 6], [2, 4, 7], [2, 4, 8], [2, 5, 6], [2, 5, 7], [2, 5, 8]] Regards Thomas
2.cartesian product - next to last version
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
3.Cartesian and polar coordinates library
Hello, For a personal project I had to create a library of cartesian and polar coordinates. Is anyone else interested in this code? If so I'll try to turn it in to a library and release it on rubyforge. Just my way of saying thanks for Ruby, this turns out to be a really nice language! Regards, Bart
4.Fastest way to compute dot product (inner product) in Ruby?
[Note: parts of this message were removed to make it a legal post.] I was wondering if anyone had any ideas on how I could make the following method "return "$#{@price}0" if "@price" only has one 0 after the ".", and just "return "$#{@price}" if it has two? Thanks. (The following method is inside a class called "Product"... Hence the subject) def price if @price.to_s.length == 4 return "$#{@price}" else @price.to_s.length return "$#{@price}0" end end
6. how to create a product instance?
Users browsing this forum: No registered users and 70 guest