Disjoint Sets

S
class Node
  attr_accessor :data, :parent, :rank, :parent, :rank

  def initialize(data)
    @data = data
    @parent = self
    @rank = 0
  end
end

class DisjointSets
  def make_set(d)
    Node.new(d)
  end

  def find_set(x)
    raise ArgumentError unless x.class <= Node

    x.parent = (find_set(x.parent)) unless x.parent == x
    x.parent
  end

  def union_set(x, y)
    px = find_set(x)
    py = find_set(y)
    return if px == py

    if px.rank > py.rank
      py.parent = px
    elsif py.rank > px.rank
      px.parent = py
    else
      px.parent = py
      py.rank += 1
    end
  end
end

ds = DisjointSets.new
one = ds.make_set(1)
two = ds.make_set(2)
three = ds.make_set(3)
ds.union_set(one, two)
puts ds.find_set(one) == ds.find_set(two) # should be true
ds.union_set(one, three)
puts ds.find_set(two) == ds.find_set(three) # should be true
puts one.rank + two.rank + three.rank == 1 # should be true