/
two_phase_set.rb
92 lines (78 loc) · 1.53 KB
/
two_phase_set.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
class Meangirls::TwoPhaseSet < Meangirls::Set
def self.biases
['r']
end
attr_accessor :a, :r
def initialize(hash = nil)
if hash
raise ArgumentError, "hash must contain a" unless hash['a']
raise ArgumentError, "hash must contain r" unless hash['r']
@a = Set.new hash['a']
@r = Set.new hash['r']
else
# Empty set
@a = Set.new
@r = Set.new
end
end
# Inserts e into the set. Raises ReinsertNotAllowed if e was previously
# deleted.
def <<(e)
if @r.include? e
raise Meangirls::ReinsertNotAllowed
end
@a << e
self
end
alias add <<
# Strict equality: both adds and removes for both 2p-sets are equal.
def ==(other)
other.kind_of? self.class and
a == other.a and
r == other.r
end
def as_json
{
'type' => type,
'a' => a.to_a,
'r' => r.to_a
}
end
def bias
'r'
end
def clone
c = super
c.a = a.clone
c.r = r.clone
c
end
# Deletes e from self. Raises DeleteNotAllowed if e does not presently
# exist.
def delete(e)
unless @a.include? e
raise Meangirls::DeleteNotAllowed
end
@r << e
e
end
# Merge with another 2p-set.
def merge(other)
unless other.kind_of? self.class
raise ArgumentError, "other must be a #{self.class}"
end
self.class.new(
'a' => (a | other.a),
'r' => (r | other.r)
)
end
def include?(e)
@a.include? e and not @r.include? e
end
def to_set
@a - @r
end
def type
'2p-set'
end
end