Set of real numbers: Difference between revisions
Content deleted Content added
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 |
raise ArgumentError unless valid?(lo, hi, inc_lo, 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 |
||
new_Rset(@sets.map(&:dup)) |
|||
end |
end |
||
Line 1,271: | Line 1,270: | ||
def union(other) |
def union(other) |
||
⚫ | |||
ans = self.dup |
|||
⚫ | |||
return ans if sets.empty? |
|||
work = [] |
work = [] |
||
pre = sets.shift |
pre = sets.shift |
||
sets.each do |post| |
sets.each do |post| |
||
if pre.hi |
if valid?(pre.hi, post.lo, !pre.inc_hi, !post.inc_lo) |
||
work << pre |
work << pre |
||
pre = post |
pre = post |
||
else |
else |
||
if pre.hi == post.lo |
|||
unless pre.inc_hi or post.inc_lo |
|||
work << pre |
|||
pre = post.dup |
|||
next |
|||
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 |
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 |
||
new_Rset(work) |
|||
⚫ | |||
end |
end |
||
alias | union |
alias | union |
||
def intersection(other) |
def intersection(other) |
||
sets = @sets.map(&:dup) |
|||
work = [] |
work = [] |
||
other.sets.each do |oset| |
other.sets.each do |oset| |
||
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 |
work << Set[lo, hi, inc_lo, inc_hi] if valid?(lo, hi, inc_lo, inc_hi) |
||
end |
end |
||
end |
end |
||
end |
end |
||
new_Rset(work) |
|||
ans |
|||
end |
end |
||
alias & intersection |
alias & intersection |
||
def difference(other) |
def difference(other) |
||
sets = @sets.map(&:dup) |
|||
other.sets.each do |oset| |
other.sets.each do |oset| |
||
work = [] |
work = [] |
||
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 |
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 |
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 = ( |
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 |
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 |
||
sets = work |
|||
end |
end |
||
new_Rset(sets) |
|||
end |
end |
||
alias - difference |
alias - difference |
||
# symmetric difference |
|||
def ^(other) |
|||
(self - other) | (other - self) |
|||
⚫ | |||
def ==(other) |
|||
return false if self.class != other.class |
|||
@sets == other.sets |
|||
end |
|||
def to_s |
def to_s |
||
"#{self.class}" + @sets.map |
"#{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 |
|||
⚫ | |||
end |
|||
def valid?(lo, hi, inc_lo, 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 |
||
test_set = ["x = Rset[0,2] | Rset(3,7) | Rset[8,10]", |
|||
"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)] |
|||
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) |