set.go
package main
type Set interface {
Add ( i interface { } ) bool
Cardinality ( ) int
Clear ( )
Clone ( ) Set
Contains ( i ... interface { } ) bool
Difference ( other Set) Set
Equal ( other Set) bool
Intersect ( other Set) Set
IsProperSubset ( other Set) bool
IsProperSuperset ( other Set) bool
IsSubset ( other Set) bool
IsSuperset ( other Set) bool
Each ( func ( interface { } ) bool )
Iter ( ) <- chan interface { }
Iterator ( ) * Iterator
Remove ( i interface { } )
String ( ) string
SymmetricDifference ( other Set) Set
Union ( other Set) Set
Pop ( ) interface { }
PowerSet ( ) Set
CartesianProduct ( other Set) Set
ToSlice ( ) [ ] interface { }
}
func NewSet ( s ... interface { } ) Set {
set := newThreadSafeSet ( )
for _ , item := range s{
set. Add ( item)
}
return & set
}
func NewSetFromSlice ( s [ ] interface { } ) Set {
a := NewSet ( s... )
return a
}
func NewSetWith ( elts ... interface { } ) Set {
return NewSetFromSlice ( elts)
}
func NewThreadUnsafeSet ( ) Set {
set := newThreadUnsafeSet ( )
return & set
}
func NewThreadUnsafeSetFromSlice ( s [ ] interface { } ) Set {
a := NewThreadUnsafeSet ( )
for _ , item := range s {
a. Add ( item)
}
return a
}
threadUnsafeSet.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
type threadUnsafeSet map [ interface { } ] struct { }
func newThreadUnsafeSet ( ) threadUnsafeSet {
return make ( threadUnsafeSet)
}
func ( set * threadUnsafeSet) Add ( i interface { } ) bool {
_ , found := ( * set) [ i]
if found {
return false
}
( * set) [ i] = struct { } { }
return true
}
func ( set * threadUnsafeSet) Contains ( i ... interface { } ) bool {
for _ , v := range i{
if _ , ok := ( * set) [ v] ; ! ok{
return false
}
}
return true
}
func ( set * threadUnsafeSet) Pop ( ) interface { } {
for item := range * set {
delete ( * set, item)
return item
}
return nil
}
func ( set * threadUnsafeSet) String ( ) string {
items := make ( [ ] string , 0 , len ( * set) )
for elem := range * set{
items = append ( items, fmt. Sprintf ( "%v" , elem) )
}
return fmt. Sprintf ( "Set{%s}" , strings. Join ( items, "," ) )
}
func ( set * threadUnsafeSet) ToSlice ( ) [ ] interface { } {
keys := make ( [ ] interface { } , 0 , set. Cardinality ( ) )
for elem := range * set{
keys = append ( keys, elem)
}
return keys
}
func ( set * threadUnsafeSet) Cardinality ( ) int {
return len ( * set)
}
func ( set * threadUnsafeSet) Clear ( ) {
* set = newThreadUnsafeSet ( )
}
func ( set * threadUnsafeSet) Clone ( ) Set {
clonedSet := newThreadUnsafeSet ( )
for _ , v := range * set{
clonedSet[ v] = v
}
return & clonedSet
}
func ( set * threadUnsafeSet) Equal ( other Set) bool {
_ = other. ( * threadUnsafeSet)
if set. Cardinality ( ) != other. Cardinality ( ) {
return false
}
for elem := range * set{
if ! other. Contains ( elem) {
return false
}
}
return true
}
func ( set * threadUnsafeSet) Remove ( i interface { } ) {
delete ( * set, i)
}
func ( set * threadUnsafeSet) Union ( other Set) Set {
o := ( other) . ( * threadUnsafeSet)
unionedSet := newThreadUnsafeSet ( )
for elem := range * set{
unionedSet. Add ( elem)
}
for elem := range * o{
unionedSet. Add ( elem)
}
return & unionedSet
}
func ( set * threadUnsafeSet) Difference ( other Set) Set {
_ = other. ( * threadUnsafeSet)
difference := newThreadUnsafeSet ( )
for elem := range * set {
if ! other. Contains ( elem) {
difference. Add ( elem)
}
}
return & difference
}
func ( set * threadUnsafeSet) SymmetricDifference ( other Set) Set {
_ = other. ( * threadUnsafeSet)
aDiff := set. Difference ( other)
bDiff := other. Difference ( set)
return aDiff. Union ( bDiff)
}
func ( set * threadUnsafeSet) IsProperSuperset ( other Set) bool {
return set. IsSubset ( other) && ! set. Equal ( other)
}
func ( set * threadUnsafeSet) IsSubset ( other Set) bool {
_ = other. ( * threadUnsafeSet)
if set. Cardinality ( ) > other. Cardinality ( ) {
return false
}
for elem := range * set{
if ! other. Contains ( elem) {
return false
}
}
return true
}
func ( set * threadUnsafeSet) IsSuperset ( other Set) bool {
return other. IsSubset ( set)
}
func ( set * threadUnsafeSet) Intersect ( other Set) Set {
o := other. ( * threadUnsafeSet)
intersection := newThreadUnsafeSet ( )
if set. Cardinality ( ) < other. Cardinality ( ) {
for elem := range * set {
if other. Contains ( elem) {
intersection. Add ( elem)
}
}
} else {
for elem := range * o {
if set. Contains ( elem) {
intersection. Add ( elem)
}
}
}
return & intersection
}
func ( set * threadUnsafeSet) Each ( cb func ( interface { } ) bool ) {
for elem := range * set {
if cb ( elem) {
break
}
}
}
func ( set * threadUnsafeSet) Iter ( ) <- chan interface { } {
ch := make ( chan interface { } )
go func ( ) {
for elem := range * set {
ch <- elem
}
close ( ch)
} ( )
return ch
}
func ( set * threadUnsafeSet) Iterator ( ) * Iterator {
iterator, ch, stopCh := newIterator ( )
go func ( ) {
L:
for elem := range * set {
select {
case <- stopCh:
break L
case ch <- elem:
}
}
close ( ch)
} ( )
return iterator
}
func ( set * threadUnsafeSet) MarshalJSON ( ) ( [ ] byte , error ) {
items := make ( [ ] string , 0 , set. Cardinality ( ) )
for elem := range * set {
b, err := json. Marshal ( elem)
if err != nil {
return nil , err
}
items = append ( items, string ( b) )
}
return [ ] byte ( fmt. Sprintf ( "[%s]" , strings. Join ( items, "," ) ) ) , nil
}
func ( set * threadUnsafeSet) UnmarshalJSON ( b [ ] byte ) error {
var i [ ] interface { }
d := json. NewDecoder ( bytes. NewReader ( b) )
d. UseNumber ( )
err := d. Decode ( & i)
if err != nil {
return err
}
for _ , v := range i {
switch t := v. ( type ) {
case [ ] interface { } , map [ string ] interface { } :
continue
default :
set. Add ( t)
}
}
return nil
}
func ( set * threadUnsafeSet) PowerSet ( ) Set {
panic ( "implement me" )
}
func ( set * threadUnsafeSet) IsProperSubset ( other Set) bool {
return other. IsProperSubset ( set)
}
type OrderedPair struct {
First interface { }
Second interface { }
}
func ( set * threadUnsafeSet) CartesianProduct ( other Set) Set {
o := other. ( * threadUnsafeSet)
cartProduct := newThreadUnsafeSet ( )
for i := range * set{
for j := range * o{
elem := OrderedPair{ First: i, Second: j}
cartProduct. Add ( elem)
}
}
return & cartProduct
}
func ( pair * OrderedPair) Equal ( other OrderedPair) bool {
if pair. First == other. First &&
pair. Second == other. Second {
return true
}
return false
}
threadSafeSet
package main
import "sync"
type threadSafeSet struct {
s threadUnsafeSet
sync. RWMutex
}
func newThreadSafeSet ( ) threadSafeSet {
return threadSafeSet{ s : newThreadUnsafeSet ( ) }
}
func ( set * threadSafeSet) Add ( i interface { } ) bool {
set. Lock ( )
ret := set. s. Add ( i)
set. Unlock ( )
return ret
}
func ( set * threadSafeSet) Contains ( i ... interface { } ) bool {
set. RLock ( )
ret := set. s. Contains ( i... )
set. RUnlock ( )
return ret
}
func ( set * threadSafeSet) IsSubset ( other Set) bool {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
ret := set. s. IsSubset ( & o. s)
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) IsProperSubset ( other Set) bool {
o := other. ( * threadSafeSet)
set. RLock ( )
defer set. RUnlock ( )
o. RLock ( )
defer o. RUnlock ( )
return set. s. IsProperSubset ( & o. s)
}
func ( set * threadSafeSet) IsSuperset ( other Set) bool {
return other. IsSubset ( set)
}
func ( set * threadSafeSet) IsProperSuperset ( other Set) bool {
return other. IsProperSubset ( set)
}
func ( set * threadSafeSet) Union ( other Set) Set {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
unsafeUnion := set. s. Union ( & o. s) . ( * threadUnsafeSet)
ret := & threadSafeSet{ s: * unsafeUnion}
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) Intersect ( other Set) Set {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
unsafeIntersection := set. s. Intersect ( & o. s) . ( * threadUnsafeSet)
ret := & threadSafeSet{ s: * unsafeIntersection}
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) Difference ( other Set) Set {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
unsafeDifference := set. s. Difference ( & o. s) . ( * threadUnsafeSet)
ret := & threadSafeSet{ s: * unsafeDifference}
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) SymmetricDifference ( other Set) Set {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
unsafeDifference := set. s. SymmetricDifference ( & o. s) . ( * threadUnsafeSet)
ret := & threadSafeSet{ s: * unsafeDifference}
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) Clear ( ) {
set. Lock ( )
set. s = newThreadUnsafeSet ( )
set. Unlock ( )
}
func ( set * threadSafeSet) Remove ( i interface { } ) {
set. Lock ( )
delete ( set. s, i)
set. Unlock ( )
}
func ( set * threadSafeSet) Cardinality ( ) int {
set. RLock ( )
defer set. RUnlock ( )
return len ( set. s)
}
func ( set * threadSafeSet) Each ( cb func ( interface { } ) bool ) {
set. RLock ( )
for elem := range set. s {
if cb ( elem) {
break
}
}
set. RUnlock ( )
}
func ( set * threadSafeSet) Iter ( ) <- chan interface { } {
ch := make ( chan interface { } )
go func ( ) {
set. RLock ( )
for elem := range set. s {
ch <- elem
}
close ( ch)
set. RUnlock ( )
} ( )
return ch
}
func ( set * threadSafeSet) Iterator ( ) * Iterator {
iterator, ch, stopCh := newIterator ( )
go func ( ) {
set. RLock ( )
L:
for elem := range set. s {
select {
case <- stopCh:
break L
case ch <- elem:
}
}
close ( ch)
set. RUnlock ( )
} ( )
return iterator
}
func ( set * threadSafeSet) Equal ( other Set) bool {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
ret := set. s. Equal ( & o. s)
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) Clone ( ) Set {
set. RLock ( )
unsafeClone := set. s. Clone ( ) . ( * threadUnsafeSet)
ret := & threadSafeSet{ s: * unsafeClone}
set. RUnlock ( )
return ret
}
func ( set * threadSafeSet) String ( ) string {
set. RLock ( )
ret := set. s. String ( )
set. RUnlock ( )
return ret
}
func ( set * threadSafeSet) PowerSet ( ) Set {
set. RLock ( )
unsafePowerSet := set. s. PowerSet ( ) . ( * threadUnsafeSet)
set. RUnlock ( )
ret := & threadSafeSet{ s: newThreadUnsafeSet ( ) }
for subset := range unsafePowerSet. Iter ( ) {
unsafeSubset := subset. ( * threadUnsafeSet)
ret. Add ( & threadSafeSet{ s: * unsafeSubset} )
}
return ret
}
func ( set * threadSafeSet) Pop ( ) interface { } {
set. Lock ( )
defer set. Unlock ( )
return set. s. Pop ( )
}
func ( set * threadSafeSet) CartesianProduct ( other Set) Set {
o := other. ( * threadSafeSet)
set. RLock ( )
o. RLock ( )
unsafeCartProduct := set. s. CartesianProduct ( & o. s) . ( * threadUnsafeSet)
ret := & threadSafeSet{ s: * unsafeCartProduct}
set. RUnlock ( )
o. RUnlock ( )
return ret
}
func ( set * threadSafeSet) ToSlice ( ) [ ] interface { } {
keys := make ( [ ] interface { } , 0 , set. Cardinality ( ) )
set. RLock ( )
for elem := range set. s {
keys = append ( keys, elem)
}
set. RUnlock ( )
return keys
}
func ( set * threadSafeSet) MarshalJSON ( ) ( [ ] byte , error ) {
set. RLock ( )
b, err := set. s. MarshalJSON ( )
set. RUnlock ( )
return b, err
}
func ( set * threadSafeSet) UnmarshalJSON ( p [ ] byte ) error {
set. RLock ( )
err := set. s. UnmarshalJSON ( p)
set. RUnlock ( )
return err
}