ごとけんです
同値類のとっても単純なモジュールを書きました。
需要があれば充実させて再度公開つもりですので、
御覧下さい。
# 早い段階で名前や実装への意見を頂こうと ^^;;
今のところ、引数かブロックで与えた同値関係の商を
Family オブジェクトとして返す Equivalence#quotient
しかありません。引数とブロックが省略されると
`===' を同値関係と仮定して、その商を返します。
Family#[] は代表元を与えるとその同値類を Array
として返します。
Equivalence#quotient は each と、高速化のため
size と include? と delete を使います。
# 立石さん、石塚さんの意見はまだ活かされてません (__;
実例はこんな感じです(thanks `irb --prompt xmp'):
require "Equivalence" # also let Array include Equivalence
==>true
a = [1,2,3,4,5,6,7,8,9,10] # simple Array
==>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
q0 = a.quotient{|i,j| i%2 == j%2}
==>[[1, 3, 5, 7, 9], [2, 4, 6, 8, 10]]
q0[1] # equivalece class for the reprezentative 1
==>[1, 3, 5, 7, 9]
q0[0] # ditto for 0 (will be nil since !a.include? 0)
==>nil
-- gotoken
#
# Equivalence.rb
#
module Equivalence
def quotient(rel = :===, &cmp)
__res__ = []
__dup__ = self.dup
if iterator?
each{|i|
if (__dup__.include? i) && (__dup__.size > 0)
__res__ |= [foo = __dup__.find_all{|j| cmp.call(i,j)}]
foo.each{|i| __dup__.delete i}
end
}
else
each{|i|
if (__dup__.include? i) && (__dup__.size > 0)
__res__ |= [foo = __dup__.find_all{|j| j.__send__(rel, i)}]
foo.each{|i| __dup__.delete i}
end
}
end
Family.new __res__
end
class Family
def initialize(ary)
@body = ary.sort
end
def inspect
@body.inspect
end
def to_s
@body.to_s
end
def [] x
@body.find{|s| s.include? x}
end
def method_missing(id, *arg, &blk)
@body.__send__(id, *arg, &blk)
end
end
end
class Array
include Equivalence
end
# end of Equivalence.rb