parent
cf2faf8334
commit
0d13d11069
@ -0,0 +1,115 @@
|
||||
package sorted
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitlab.com/Pixdigit/uniqueID"
|
||||
)
|
||||
|
||||
type Set struct {
|
||||
elems []*setElem
|
||||
}
|
||||
|
||||
type uniqueElem interface {
|
||||
ID() uniqueID.ID
|
||||
}
|
||||
|
||||
type setElem struct {
|
||||
value num
|
||||
elem *uniqueElem
|
||||
}
|
||||
|
||||
func (se *setElem) ID() uniqueID.ID {
|
||||
return se.elem.ID()
|
||||
}
|
||||
|
||||
func (s *Set) Insert(uElem *uniqueElem, value num) error {
|
||||
for _, elem := range s.elems {
|
||||
if elem.ID() == uElem.ID() {
|
||||
return &ErrDuplicateElement{"element already present in set"}
|
||||
}
|
||||
}
|
||||
|
||||
newElem := setElem{
|
||||
value,
|
||||
uElem,
|
||||
}
|
||||
|
||||
if len(s.elems) == 0 {
|
||||
s.elems = append(s.elems, &newElem)
|
||||
} else {
|
||||
|
||||
//find i such that s.elems[i].value < newElen.value
|
||||
var i int
|
||||
for i = 0; i < len(s.elems) && s.elems[i].value < newElem.value; i++ {
|
||||
}
|
||||
|
||||
//actual instertion at index = i
|
||||
previousElems := s.elems[:i]
|
||||
forwardElems := make([]*setElem, len(s.elems[i:]))
|
||||
copy(forwardElems, s.elems[i:])
|
||||
|
||||
s.elems = append(previousElems, &newElem)
|
||||
s.elems = append(s.elems, forwardElems...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Set) Nearest(value num) (interface{}, error) {
|
||||
|
||||
if len(s.elems) == 0 {
|
||||
return setElem{}, &ErrListEmpty{"List has no nearest element"}
|
||||
}
|
||||
|
||||
if s.elems[0].value > value {
|
||||
return s.elems[0].elem, nil
|
||||
} else if len(s.elems) == 1 {
|
||||
return s.elems[0].elem, nil
|
||||
} else {
|
||||
//Find i such that s.elems[i].value > value
|
||||
var i int
|
||||
for i = 1; i < len(s.elems) && s.elems[i].value < value; i++ {
|
||||
}
|
||||
//If there is no bigger elemet return last element
|
||||
if i == len(s.elems) {
|
||||
return s.elems[i-1].elem, nil
|
||||
|
||||
}
|
||||
biggerElem := s.elems[i]
|
||||
smallerElem := s.elems[i-1]
|
||||
|
||||
//Return the element closer to value
|
||||
switch {
|
||||
case (value - smallerElem.value) <= (biggerElem.value - value):
|
||||
return smallerElem.elem, nil
|
||||
case (value - smallerElem.value) > (biggerElem.value - value):
|
||||
return biggerElem.elem, nil
|
||||
}
|
||||
}
|
||||
panic("reached unreachable statement")
|
||||
}
|
||||
|
||||
func (s *Set) String() string {
|
||||
str := "["
|
||||
for i, v := range s.elems {
|
||||
if i != 0 {
|
||||
str += " "
|
||||
}
|
||||
str += fmt.Sprintf("%v", v.elem)
|
||||
}
|
||||
str += "]"
|
||||
return str
|
||||
}
|
||||
|
||||
func (s *Set) Elems() []*setElem {
|
||||
return s.elems
|
||||
}
|
||||
|
||||
func (s *Set) Contains(testID uniqueID.ID) bool {
|
||||
for _, elem := range s.elems {
|
||||
if elem.ID() == testID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package sorted
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
tools "gitlab.com/Pixdigit/goTestTools"
|
||||
"gitlab.com/Pixdigit/uniqueID"
|
||||
)
|
||||
|
||||
type testElem struct {
|
||||
id uniqueID.ID
|
||||
Name string
|
||||
}
|
||||
|
||||
func NewSampleElem(IDSpace uniqueID.IDSpace, name string) *testElem {
|
||||
return &testElem{
|
||||
IDSpace.NewID(),
|
||||
name,
|
||||
}
|
||||
}
|
||||
func (te *testElem) ID() uniqueID.ID {
|
||||
return te.id
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
|
||||
testIDSpace := uniqueID.IDSpace{}
|
||||
set := Set{}
|
||||
|
||||
set.Insert(NewSampleElem(testIDSpace, "a"), 1)
|
||||
set.Insert(NewSampleElem(testIDSpace, "b"), 2)
|
||||
set.Insert(NewSampleElem(testIDSpace, "c"), 3)
|
||||
set.Insert(NewSampleElem(testIDSpace, "d"), 5)
|
||||
set.Insert(NewSampleElem(testIDSpace, "e"), 4)
|
||||
value, err := set.Nearest(3.2); if err != nil {tools.WrapErr(err, "could not get element from set", t)}
|
||||
tools.Test(value == "c", "did not get corrent element", t)
|
||||
value, err = set.Nearest(3.8); if err != nil {tools.WrapErr(err, "could not get element from set", t)}
|
||||
tools.Test(value == "e", "did not get corrent element", t)
|
||||
value, err = set.Nearest(8); if err != nil {tools.WrapErr(err, "could not get element from set", t)}
|
||||
tools.Test(value == "d", "did not get corrent element", t)
|
||||
value, err = set.Nearest(-2); if err != nil {tools.WrapErr(err, "could not get element from set", t)}
|
||||
tools.Test(value == "a", "did not get corrent element", t)
|
||||
value, err = set.Nearest(2); if err != nil {tools.WrapErr(err, "could not get element from set", t)}
|
||||
tools.Test(value == "b", "did not get corrent element", t)
|
||||
|
||||
t.Log(set.String())
|
||||
|
||||
}
|
Loading…
Reference in new issue