// License: GPLv3 Copyright: 2023, Kovid Goyal, package utils import ( "fmt" ) var _ = fmt.Print func Keys[M ~map[K]V, K comparable, V any](m M) []K { r := make([]K, 0, len(m)) for k := range m { r = append(r, k) } return r } func Values[M ~map[K]V, K comparable, V any](m M) []V { r := make([]V, 0, len(m)) for _, k := range m { r = append(r, k) } return r } type Set[T comparable] struct { items map[T]struct{} } func (self *Set[T]) Add(val T) { self.items[val] = struct{}{} } func (self *Set[T]) AddItems(val ...T) { for _, x := range val { self.items[x] = struct{}{} } } func (self *Set[T]) String() string { return fmt.Sprintf("%#v", Keys(self.items)) } func (self *Set[T]) Remove(val T) { delete(self.items, val) } func (self *Set[T]) Discard(val T) { delete(self.items, val) } func (self *Set[T]) Has(val T) bool { _, ok := self.items[val] return ok } func (self *Set[T]) Clear() { clear(self.items) } func (self *Set[T]) Len() int { return len(self.items) } func (self *Set[T]) ForEach(f func(T)) { for x := range self.items { f(x) } } func (self *Set[T]) Iterable() map[T]struct{} { return self.items } func (self *Set[T]) AsSlice() []T { return Keys(self.items) } func (self *Set[T]) Intersect(other *Set[T]) (ans *Set[T]) { if other == nil { return NewSet[T]() } if self.Len() < other.Len() { ans = NewSet[T](self.Len()) for x := range self.items { if _, ok := other.items[x]; ok { ans.items[x] = struct{}{} } } } else { ans = NewSet[T](other.Len()) for x := range other.items { if _, ok := self.items[x]; ok { ans.items[x] = struct{}{} } } } return } func (self *Set[T]) Subtract(other *Set[T]) (ans *Set[T]) { ans = NewSet[T](self.Len()) for x := range self.items { if other == nil || !other.Has(x) { ans.items[x] = struct{}{} } } return ans } func (self *Set[T]) IsSubsetOf(other *Set[T]) bool { if other == nil { return self.Len() == 0 } for x := range self.items { if !other.Has(x) { return false } } return true } func (self *Set[T]) Equal(other *Set[T]) bool { l := self.Len() if other == nil { return l == 0 } if l != other.Len() { return false } for x := range self.items { if !other.Has(x) { return false } } return true } func NewSet[T comparable](capacity ...int) (ans *Set[T]) { if len(capacity) == 0 { ans = &Set[T]{items: make(map[T]struct{}, 8)} } else { ans = &Set[T]{items: make(map[T]struct{}, capacity[0])} } return } func NewSetWithItems[T comparable](items ...T) (ans *Set[T]) { ans = NewSet[T](len(items)) ans.AddItems(items...) return ans }