internal/pieceordering: Switch to a different skiplist implementation

This commit is contained in:
Matt Joiner 2014-12-06 21:15:03 -06:00
parent 3c41002317
commit 9be0f6463f
2 changed files with 79 additions and 23 deletions

View File

@ -1,17 +1,19 @@
package pieceordering
import (
"github.com/glenn-brown/skiplist"
"math/rand"
"github.com/ryszard/goskiplist/skiplist"
)
type Instance struct {
sl *skiplist.T
sl *skiplist.SkipList
pieceKeys map[int]int
}
func New() *Instance {
return &Instance{
sl: skiplist.New(),
sl: skiplist.NewIntMap(),
}
}
@ -24,19 +26,48 @@ func (me *Instance) SetPiece(piece, key int) {
}
me.removeKeyPiece(existingKey, piece)
}
me.sl.Insert(key, piece)
var itemSl []int
if exItem, ok := me.sl.Get(key); ok {
itemSl = exItem.([]int)
}
me.sl.Set(key, append(itemSl, piece))
if me.pieceKeys == nil {
me.pieceKeys = make(map[int]int)
}
me.pieceKeys[piece] = key
me.shuffleItem(key)
}
func (me *Instance) shuffleItem(key int) {
_item, ok := me.sl.Get(key)
if !ok {
return
}
item := _item.([]int)
for i := range item {
j := i + rand.Intn(len(item)-i)
item[i], item[j] = item[j], item[i]
}
me.sl.Set(key, item)
}
func (me *Instance) removeKeyPiece(key, piece int) {
if me.sl.Remove(key).Value.(int) != piece {
panic("piecekeys map lied to us")
item, ok := me.sl.Get(key)
if !ok {
panic("no item for key")
}
if me.sl.Remove(key) != nil {
panic("duplicate key")
itemSl := item.([]int)
for i, piece1 := range itemSl {
if piece1 == piece {
itemSl[i] = itemSl[len(itemSl)-1]
itemSl = itemSl[:len(itemSl)-1]
break
}
}
if len(itemSl) == 0 {
me.sl.Delete(key)
} else {
me.sl.Set(key, itemSl)
}
}
@ -50,11 +81,11 @@ func (me *Instance) DeletePiece(piece int) {
}
func (me Instance) First() Element {
e := me.sl.Front()
if e == nil {
i := me.sl.SeekToFirst()
if i == nil {
return nil
}
return element{e}
return &element{i, i.Value().([]int)}
}
type Element interface {
@ -63,17 +94,23 @@ type Element interface {
}
type element struct {
sle *skiplist.Element
i skiplist.Iterator
sl []int
}
func (e element) Next() Element {
sle := e.sle.Next()
if sle == nil {
func (e *element) Next() Element {
e.sl = e.sl[1:]
if len(e.sl) > 0 {
return e
}
ok := e.i.Next()
if !ok {
return nil
}
return element{sle}
e.sl = e.i.Value().([]int)
return e
}
func (e element) Piece() int {
return e.sle.Value.(int)
return e.sl[0]
}

View File

@ -1,6 +1,7 @@
package pieceordering
import (
"sort"
"testing"
)
@ -11,16 +12,34 @@ func instanceSlice(i *Instance) (sl []int) {
return
}
func checkOrder(t *testing.T, i *Instance, pp []int) {
func sameContents(a, b []int) bool {
if len(a) != len(b) {
panic("y u pass different length slices")
}
sort.IntSlice(a).Sort()
sort.IntSlice(b).Sort()
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func checkOrder(t *testing.T, i *Instance, ppp ...[]int) {
fatal := func() {
t.Fatalf("have %v, expected %v", instanceSlice(i), pp)
t.Fatalf("have %v, expected %v", instanceSlice(i), ppp)
}
e := i.First()
for _, p := range pp {
if p != e.Piece() {
for _, pp := range ppp {
var pp_ []int
for len(pp_) != len(pp) {
pp_ = append(pp_, e.Piece())
e = e.Next()
}
if !sameContents(pp, pp_) {
fatal()
}
e = e.Next()
}
if e != nil {
fatal()
@ -47,7 +66,7 @@ func TestPieceOrdering(t *testing.T) {
checkOrder(t, i, []int{3, 1, 2})
// Move a piece that isn't the youngest in a key.
i.SetPiece(1, -1)
checkOrder(t, i, []int{1, 3, 2})
checkOrder(t, i, []int{1}, []int{3, 2})
i.DeletePiece(2)
i.DeletePiece(3)
i.DeletePiece(1)