2021 Day 8
This commit is contained in:
parent
0f454c5d1f
commit
2d203e541e
3 changed files with 336 additions and 0 deletions
108
2021/aoc/stringset/stringset.go
Normal file
108
2021/aoc/stringset/stringset.go
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package stringset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type StringSet map[string]struct{}
|
||||
|
||||
func Slice(vals []string) StringSet {
|
||||
set := make(StringSet)
|
||||
for _, v := range vals {
|
||||
set[v] = struct{}{}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func Runes(v string) StringSet {
|
||||
return Slice(strings.Split(v, ""))
|
||||
}
|
||||
|
||||
func (s StringSet) String() string {
|
||||
var elts []string
|
||||
for e := range s {
|
||||
elts = append(elts, e)
|
||||
}
|
||||
sort.Strings(elts)
|
||||
return fmt.Sprintf("{%s}", strings.Join(elts, ", "))
|
||||
}
|
||||
|
||||
func (s StringSet) Only() string {
|
||||
if len(s) > 1 {
|
||||
panic(fmt.Sprintf("too many elements: %s", s))
|
||||
}
|
||||
for v := range s {
|
||||
return v
|
||||
}
|
||||
panic("empty set")
|
||||
}
|
||||
|
||||
func (s StringSet) Has(elt string) bool {
|
||||
_, ok := s[elt]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (s StringSet) add(elt string) {
|
||||
s[elt] = struct{}{}
|
||||
}
|
||||
|
||||
func (s StringSet) Union(t StringSet) StringSet {
|
||||
set := make(StringSet)
|
||||
for a := range s {
|
||||
set.add(a)
|
||||
}
|
||||
for b := range t {
|
||||
set.add(b)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (s StringSet) Intersect(t StringSet) StringSet {
|
||||
set := make(StringSet)
|
||||
for a := range s {
|
||||
if t.Has(a) {
|
||||
set.add(a)
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (s StringSet) Minus(t StringSet) StringSet {
|
||||
set := make(StringSet)
|
||||
for a := range s {
|
||||
if !t.Has(a) {
|
||||
set.add(a)
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (s StringSet) Equal(t StringSet) bool {
|
||||
if len(s) != len(t) {
|
||||
return false
|
||||
}
|
||||
for a := range s {
|
||||
if !t.Has(a) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func Union(sets ...StringSet) StringSet {
|
||||
t := make(StringSet)
|
||||
for _, s := range sets {
|
||||
t = t.Union(s)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func Intersect(sets ...StringSet) StringSet {
|
||||
t := Union(sets...)
|
||||
for _, s := range sets {
|
||||
t = t.Intersect(s)
|
||||
}
|
||||
return t
|
||||
}
|
||||
40
2021/aoc/stringset/stringset_test.go
Normal file
40
2021/aoc/stringset/stringset_test.go
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package stringset_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jdkaplan/advent-of-code/aoc/stringset"
|
||||
)
|
||||
|
||||
func TestMinus(t *testing.T) {
|
||||
a := stringset.Runes("dab")
|
||||
b := stringset.Runes("ab")
|
||||
u := a.Minus(b)
|
||||
if n := len(u); n != 1 {
|
||||
t.Fatalf("Expected one value, got %d", n)
|
||||
}
|
||||
if v := u.Only(); v != "d" {
|
||||
t.Errorf(`Expected value to be "d", got %s`, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersect(t *testing.T) {
|
||||
t.Run("pairwise", func(t *testing.T) {
|
||||
u := stringset.Runes("dab").Intersect(stringset.Runes("ab"))
|
||||
expected := stringset.Runes("ab")
|
||||
if !u.Equal(expected) {
|
||||
t.Errorf(`Expected value to be %s, got %s`, expected, u)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("multiple", func(t *testing.T) {
|
||||
u := stringset.Intersect(
|
||||
stringset.Runes("dab"),
|
||||
stringset.Runes("ab"),
|
||||
)
|
||||
expected := stringset.Runes("ab")
|
||||
if !u.Equal(expected) {
|
||||
t.Errorf(`Expected value to be %s, got %s`, expected, u)
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Reference in a new issue