Set of real numbers: Difference between revisions

Content deleted Content added
Grondilu (talk | contribs)
ok, convex is actually fine
→‎{{header|Ruby}}: add methods (new_Rset, valid?, ^, ==)
Line 1,238: Line 1,238:
else
else
raise TypeError unless lo.is_a?(Numeric) and hi.is_a?(Numeric)
raise TypeError unless lo.is_a?(Numeric) and hi.is_a?(Numeric)
raise ArgumentError unless lo <= hi
raise ArgumentError unless valid?(lo, hi, inc_lo, inc_hi)
raise ArgumentError unless lo != hi or (inc_lo and inc_hi)
@sets = [Set[lo, hi, inc_lo, inc_hi]]
@sets = [Set[lo, hi, inc_lo, inc_hi]]
end
end
Line 1,250: Line 1,249:
def self.from_s(str)
def self.from_s(str)
raise ArgumentError unless str =~ /(\[|\()(.+),(.+)(\]|\))/
raise ArgumentError unless str =~ /(\[|\()(.+),(.+)(\]|\))/
b0, lo, hi, b1 = $~.captures
b0, lo, hi, b1 = $~.captures # $~ : Regexp.last_match
lo = Rational(lo)
lo = Rational(lo)
lo = lo.numerator if lo.denominator == 1
lo = lo.numerator if lo.denominator == 1
Line 1,259: Line 1,258:
def dup
def dup
Marshal.load(Marshal.dump(self))
new_Rset(@sets.map(&:dup))
end
end
Line 1,271: Line 1,270:
def union(other)
def union(other)
sets = (@sets+other.sets).map(&:dup).sort_by{|set| [set.lo, set.hi]}
ans = self.dup
sets = (ans.sets+other.sets).sort_by{|set| [set.lo, set.hi]}
return ans if sets.empty?
work = []
work = []
pre = sets.shift.dup
pre = sets.shift
sets.each do |post|
sets.each do |post|
if pre.hi < post.lo
if valid?(pre.hi, post.lo, !pre.inc_hi, !post.inc_lo)
work << pre
work << pre
pre = post.dup
pre = post
else
else
if pre.hi == post.lo
unless pre.inc_hi or post.inc_lo
work << pre
pre = post.dup
next
end
end
pre.inc_lo |= post.inc_lo if pre.lo == post.lo
pre.inc_lo |= post.inc_lo if pre.lo == post.lo
if pre.hi < post.hi
if pre.hi < post.hi
pre.hi = post.hi
pre.hi = post.hi
pre.inc_hi = post.inc_hi
pre.inc_hi = post.inc_hi
elsif post.hi == pre.hi
elsif pre.hi == post.hi
pre.inc_hi |= post.inc_hi
pre.inc_hi |= post.inc_hi
end
end
Line 1,298: Line 1,288:
end
end
work << pre if pre
work << pre if pre
ans.sets = work
new_Rset(work)
ans
end
end
alias | union
alias | union
def intersection(other)
def intersection(other)
ans = self.dup
sets = @sets.map(&:dup)
work = []
work = []
other.sets.each do |oset|
other.sets.each do |oset|
ans.sets.each do |set|
sets.each do |set|
if set.hi < oset.lo or oset.hi < set.lo
if set.hi < oset.lo or oset.hi < set.lo
# ignore
# ignore
Line 1,329: Line 1,318:
inc_hi = set.inc_hi && oset.inc_hi
inc_hi = set.inc_hi && oset.inc_hi
end
end
work << Set[lo, hi, inc_lo, inc_hi] if lo != hi or (inc_lo and inc_hi)
work << Set[lo, hi, inc_lo, inc_hi] if valid?(lo, hi, inc_lo, inc_hi)
end
end
end
end
end
end
ans.sets = work
new_Rset(work)
ans
end
end
alias & intersection
alias & intersection
def difference(other)
def difference(other)
ans = self.dup
sets = @sets.map(&:dup)
other.sets.each do |oset|
other.sets.each do |oset|
work = []
work = []
ans.sets.each do |set|
sets.each do |set|
if set.hi < oset.lo or oset.hi < set.lo
if set.hi < oset.lo or oset.hi < set.lo
work << set
work << set
Line 1,349: Line 1,337:
else
else
if set.lo < oset.lo
if set.lo < oset.lo
inc_hi = (set.hi==oset.lo and not set.inc_hi) ? false : (not oset.inc_lo)
inc_hi = (set.hi==oset.lo and !set.inc_hi) ? false : !oset.inc_lo
work << Set[set.lo, oset.lo, set.inc_lo, inc_hi]
work << Set[set.lo, oset.lo, set.inc_lo, inc_hi]
elsif set.lo == oset.lo and set.inc_lo and (not oset.inc_lo)
elsif valid?(set.lo, oset.lo, set.inc_lo, !oset.inc_lo)
work << Set[set.lo, set.lo, true, true]
work << Set[set.lo, set.lo, true, true]
end
end
if oset.hi < set.hi
if oset.hi < set.hi
inc_lo = (set.lo==oset.hi and not set.inc_lo) ? false : (not oset.inc_hi)
inc_lo = (oset.hi==set.lo and !set.inc_lo) ? false : !oset.inc_hi
work << Set[oset.hi, set.hi, inc_lo, set.inc_hi]
work << Set[oset.hi, set.hi, inc_lo, set.inc_hi]
elsif set.hi == oset.hi and set.inc_hi and (not oset.inc_hi)
elsif valid?(oset.hi, set.hi, !oset.inc_hi, set.inc_hi)
work << Set[set.hi, set.hi, true, true]
work << Set[set.hi, set.hi, true, true]
end
end
end
end
end
end
ans.sets = work
sets = work
end
end
ans
new_Rset(sets)
end
end
alias - difference
alias - difference
# symmetric difference
def ^(other)
(self - other) | (other - self)
end
def ==(other)
return false if self.class != other.class
@sets == other.sets
end
def to_s
def to_s
"#{self.class}" + @sets.map {|set| set.to_s}.join(',')
"#{self.class}" + @sets.map(&:to_s).join(',')
end
end
alias inspect to_s
alias inspect to_s
protected
protected
attr_accessor :sets
attr_accessor :sets
private
def new_Rset(sets)
rset = self.class.new # empty set
rset.sets = sets
rset
end
def valid?(lo, hi, inc_lo, inc_hi)
lo < hi or (lo==hi and inc_lo and inc_hi)
end
end
end


Line 1,391: Line 1,402:
puts "#{a} | #{b} -> #{a | b}"
puts "#{a} | #{b} -> #{a | b}"
puts "#{c} | #{d} -> #{c | d}"
puts "#{c} | #{d} -> #{c | d}"

puts
puts
puts "#{a} & #{b} -> #{a & b}"
puts "#{a} & #{b} -> #{a & b}"
puts "#{c} & #{d} -> #{c & d}"
puts "#{c} & #{d} -> #{c & d}"
puts "(#{c} & #{d}).empty? -> #{(c&d).empty?}"
puts "(#{c} & #{d}).empty? -> #{(c&d).empty?}"

puts
puts
puts "#{a} - #{b} -> #{a - b}"
puts "#{a} - #{b} -> #{a - b}"
Line 1,419: Line 1,428:


puts
puts
str = "Rset[0,2] | Rset(3,7) | Rset[8,10]"
test_set = ["x = Rset[0,2] | Rset(3,7) | Rset[8,10]",
puts "x = %s -> %s" % [str, x=eval(str)]
"y = Rset(7,9) | Rset(5,6) | Rset[1,4]",
"x | y", "x & y", "x - y", "y - x", "x ^ y"]
str = "Rset(7,9) | Rset(5,6) | Rset[1,4]"
x = y = nil
puts "y = %s -> %s" % [str, y=eval(str)]
puts "x | y -> #{x | y}"
test_set.each {|str| puts "#{str} -> #{eval(str)}"}
puts "x & y -> #{x & y}"
puts "x - y -> #{x - y}"
puts "y - x -> #{y - x}"


puts
puts
Line 1,477: Line 1,483:
x - y -> Rset[0,1),(4,5],[6,7),[9,10]
x - y -> Rset[0,1),(4,5],[6,7),[9,10]
y - x -> Rset(2,3],(7,8)
y - x -> Rset(2,3],(7,8)
x ^ y -> Rset[0,1),(2,3],(4,5],[6,7),(7,8),[9,10]


a = Rset(-Infinity,Infinity)
a = Rset(-Infinity,Infinity)