Distinct Sets (#225)

Daniel,
Â
I would like to know how to install ruby and rails on my computer.
but the trouble that I am having is that all the files are zipped up
and can use them. if you have a sloution for this email me back.
[email protected]
Â
JamesÂ

— On Thu, 4/8/10, Daniel M. [email protected] wrote:

From: Daniel M. [email protected]
Subject: [QUIZ][SUMMARY] Distinct Sets (#225)
To: “ruby-talk ML” [email protected]
Date: Thursday, April 8, 2010, 3:16 PM

Many members of the Ruby Community contributed solutions to this quiz.
Some
long time veterans as well as first time contributors. Thanks everyone
for
the great turnout!

Set#divide is an interesting method that came up during the
discussion. I
was not previously familiar with it, time to learn.

    numbers = Set[1, 3, 4, 6, 9, 10, 11]
    set = numbers.divide { |i,j| (i - j).abs == 1 }
    p set   # => #<Set: {#<Set: {1}>,
             #<Set: {11, 9, 10}>,
             #<Set: {3, 4}>,
             #<Set: {6}>}>

I didn’t quite get it at first so I went to the console and tried some
other
examples.

  set = numbers.divide { |i,j| (i - j).abs == 2 }
  => #<Set: {#<Set: {10}>, #<Set: {1, 3}>, #<Set: {6, 4}>, #<Set: {11,
9}>}>

Ok, so the first example gets contiguous runs (numbers that are 1
apart),
and the second example gets contiguous skip runs (runs of numbers that
are 2
apart).

Now to test out the single argument version:

  set = numbers.divide { |i| i%2 }
  => #<Set: {#<Set: {11, 1, 3, 9}>, #<Set: {6, 4, 10}>}>

Dividing a set into odds and evens. A core component of this quiz is
grouping sets; this may come in handy.

brabuhr’s first solution uses this method and is a good illustration of
the
principle behind the problem.

  require ‘set’

  class Set
   def intersect?(other)
    other.each { |o| return true if include?(o) }
    false
   end
  end

  def distinct_sets(array_of_arrays)
   set_of_sets = array_of_arrays.map{|a|
    a.to_set
   }.to_set

   set_of_sets.divide{|i, j|
    i.intersect?(j)
   }.map{|s|
    s.flatten.to_a
   }
  end

In this solution an instance method intersect? is added to Set. This
allows us to divide all the sets that share an element into groups.
Then
all that is left is to merge the groups of sets (Set#flatten takes
care of
that) and to present the result as an array of arrays to match how the
output was specified in the quiz.

During the quiz discussion a full set of test cases was developed. This
enabled everyone to check and verify the accuracy of their solutions.
The
test suite was provided by Rob B. and uses Shoulda1, a testing
framework that provides additional helpers, macros, and assertions to
the
Test::Unit framework.

Another benefit the testing provided was the ability to focus on the
speed
at which the solutions run. When you have a full test suite you can
modify
code without fear of breaking things in order to optimize and squeeze
out
that last bit of speed, or conversely, to clean things up to improve
code
readability, knowing that you have a safety net of tests to catch any
errors
introduced.

There were many, many more solutions to this week’s quiz. The principle
of
grouping and merging the sets is followed by all solutions, with varying
tradeoffs between execution speed and readability. brabuhr had two more,
Benoit D. had two, lith had two, Rob B. had one, and first
time
correspondent Johnathon W. had one. Please be sure to take a look
inside
the archived files, there are lots of good solutions in there.

Special thanks to everyone who participated in the quiz!

Distinct Sets (#225) - Solutions3