Forum: Ruby Combinatorics and permutations? Help?

Posted by David Palm (Guest)
on 2008-03-11 12:06
(Received via mailing list)
Hi,
I have a problem involving combinatorics and permutations and my brain 
hurts.

The problem: I have a hash of products in input. I then build an array 
of equivalent products for each input product. I end up with an array 
such as this:
{
  :input_prod_1 => [:p1_1, :p1_2, ... , p1_x],
  :input_prod_2 => [:p2_1, :p2_1, ..., p2_y],
  ...
  :input_prod_m => [:pm_1, :pm_1, ..., pm_z]
}

I need all the unique combinations of each product from the first group 
with each of the second. For example:
given: [ [:p1, :p2], [:p3, p4] ]
I need to obtain: [ [:p1, :p3], [:p1, :p4], [:p2, :p3], [:p2, :p4] ]

Given: [ [:p1], [:p2, :p3, :p4] ]
I need: [ [:p1, :p2], [:p1, :p3], [:p1, :p4] ]

The number of input products is in the order of tens (max); the same 
goes for the number of equivalent products. This means the total number 
of partitions is pretty large and I need to weed out the equivalent ones 
soon/fast enough to reduce the total number.

I've been making attempts with the permutation gem all morning; looks 
like it's doing the "right thing", but frankly my maths skills are 
lacking and I can't really figure out how to use it (should I?).

Also: order is not important for the result arrays.

This is easy, right? :-/
Posted by Emmanuel Oga (emmanueloga)
on 2008-03-11 12:22
http://blade.nagaokaut.ac.jp/~sinara/ruby/math/

Have Fun :)
Posted by William James (Guest)
on 2008-03-11 12:44
(Received via mailing list)
On Mar 11, 5:06 am, David Palm <dvd...@gmail.com> wrote:

> I need all the unique combinations of each product from the first group with each of the second. For example:
> given: [ [:p1, :p2], [:p3, p4] ]
> I need to obtain: [ [:p1, :p3], [:p1, :p4], [:p2, :p3], [:p2, :p4] ]
>
> Given: [ [:p1], [:p2, :p3, :p4] ]
> I need: [ [:p1, :p2], [:p1, :p3], [:p1, :p4] ]

p [[1,2],[3,4]].inject([[]]){|old,lst|
  lst.inject([]){|new,e| new + old.map{|c| c.dup << e}}}
Posted by David Palm (Guest)
on 2008-03-11 13:29
(Received via mailing list)
On Tue, 11 Mar 2008 20:40:11 +0900, William James wrote:
> p [[1,2],[3,4]].inject([[]]){|old,lst|
>   lst.inject([]){|new,e| new + old.map{|c| c.dup << e}}}

awesome. Totally rocks.
Posted by Sergio Bayona (sergiob)
on 2010-02-08 04:29
I have a similar challenge:

given: [{"a" => [1, 2]}, {"b" => [3, 4]}]

I need: [{"a" => 1, "b" => 3}, {"a" => 1, "b" => 4}, {"a" => 2, "b" => 
3}, {"a" => 2, "b" => 4}]

Any ideas?

Thanks.
S
Posted by Jacob Mitchell (Guest)
on 2010-02-08 06:32
(Received via mailing list)
>
> given: [{"a" => [1, 2]}, {"b" => [3, 4]}]
>
> I need: [{"a" => 1, "b" => 3}, {"a" => 1, "b" => 4}, {"a" => 2, "b" =>
> 3}, {"a" => 2, "b" => 4}]
>
> Any ideas?
>
> Yup, the following method does nearly the same thing, except it takes
arrays.  You could either use this method for inspiration, or convert 
your
desired input into my array of arrays input format and then convert the
output back to your desired format.  Hope that helps.

def selections(arrays, results=[Array.new])
  return results if arrays.empty?

  new_selection_choices = arrays.shift
  results_with_new_selections = []

  results.each do |prev_selection_set|
    new_selection_choices.each do |selection|
      results_with_new_selections <<
prev_selection_set.clone.push(selection)
    end
  end

  return selections(arrays, results_with_new_selections)
end

selections([[1, 2], [3, 4]])  #=> [[1, 3], [1, 4], [2, 3], [2, 4]]
Posted by Josh Cheek (Guest)
on 2010-02-08 07:44
(Received via mailing list)
On Sun, Feb 7, 2010 at 9:29 PM, Sergio Bayona 
<bayona.sergio@gmail.com>wrote:

> S
> --
> Posted via http://www.ruby-forum.com/.
>
>
Here is a solution I have come up with (http://gist.github.com/297937). 
I
don't know how you want all edge cases to be handled, I made my best
guesses, you can see them in the tests.
Posted by Sergio Bayona (sergiob)
on 2010-02-18 17:08
Sorry took so long to respond. Your solution worked as expected. Thanks!

SB

Josh Cheek wrote:
> On Sun, Feb 7, 2010 at 9:29 PM, Sergio Bayona 
> <bayona.sergio@gmail.com>wrote:
> 
>> S
>> --
>> Posted via http://www.ruby-forum.com/.
>>
>>
> Here is a solution I have come up with (http://gist.github.com/297937). 
> I
> don't know how you want all edge cases to be handled, I made my best
> guesses, you can see them in the tests.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.