forked from torbiak/gopl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintset.go
138 lines (123 loc) · 2.62 KB
/
intset.go
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// ex6.3 is a bit vector integer set with binary set operations.
package main
import (
"bytes"
"fmt"
)
// An IntSet is a set of small non-negative integers.
// Its zero value represents the empty set.
type IntSet struct {
words []uint64
}
// Has reports whether the set contains the non-negative value x.
func (s *IntSet) Has(x int) bool {
word, bit := x/64, uint(x%64)
return word < len(s.words) && s.words[word]&(1<<bit) != 0
}
// Add adds the non-negative value x to the set.
func (s *IntSet) Add(x int) {
word, bit := x/64, uint(x%64)
for word >= len(s.words) {
s.words = append(s.words, 0)
}
s.words[word] |= 1 << bit
}
func (s *IntSet) AddAll(nums ...int) {
for _, n := range nums {
s.Add(n)
}
}
// UnionWith sets s to the union of s and t.
func (s *IntSet) UnionWith(t *IntSet) {
for i, tword := range t.words {
if i < len(s.words) {
s.words[i] |= tword
} else {
s.words = append(s.words, tword)
}
}
}
// Set s to the intersection of s and t.
func (s *IntSet) IntersectWith(t *IntSet) {
for i, tword := range t.words {
if i < len(s.words) {
s.words[i] &= tword
} else {
s.words = append(s.words, tword)
}
}
}
// Set s to the difference of s and t.
func (s *IntSet) DifferenceWith(t *IntSet) {
for i, tword := range t.words {
if i < len(s.words) {
s.words[i] &^= tword
} else {
s.words = append(s.words, tword)
}
}
}
// Set s to the symmetric difference of s and t.
func (s *IntSet) SymmetricDifference(t *IntSet) {
for i, tword := range t.words {
if i < len(s.words) {
s.words[i] ^= tword
} else {
s.words = append(s.words, tword)
}
}
}
func popcount(x uint64) int {
count := 0
for x != 0 {
count++
x &= x - 1
}
return count
}
// return the number of elements
func (s *IntSet) Len() int {
count := 0
for _, word := range s.words {
count += popcount(word)
}
return count
}
// remove x from the set
func (s *IntSet) Remove(x int) {
word, bit := x/64, uint(x%64)
s.words[word] &^= 1 << bit
}
// remove all elements from the set
func (s *IntSet) Clear() {
for i := range s.words {
s.words[i] = 0
}
}
// return a copy of the set
func (s *IntSet) Copy() *IntSet {
new := &IntSet{}
new.words = make([]uint64, len(s.words))
copy(new.words, s.words)
return new
}
// String returns the set as a string of the form "{1 2 3}".
func (s *IntSet) String() string {
var buf bytes.Buffer
buf.WriteByte('{')
for i, word := range s.words {
if word == 0 {
continue
}
for j := 0; j < 64; j++ {
if word&(1<<uint(j)) != 0 {
if buf.Len() > len("{") {
buf.WriteByte(' ')
}
fmt.Fprintf(&buf, "%d", 64*i+j)
}
}
}
buf.WriteByte('}')
return buf.String()
}