Skip to content

Commit

Permalink
Define and test readOnlyCellQueue and readOnlyCellQueueGetter, both o…
Browse files Browse the repository at this point in the history
…f which implement queue and queueGetter.
  • Loading branch information
jkomoros committed Jul 11, 2016
1 parent 538fdbb commit 7c40d90
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 4 deletions.
70 changes: 70 additions & 0 deletions finite_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sudoku

import (
"math/rand"
"sort"
"sync"
)

Expand All @@ -18,6 +19,16 @@ type queueGetter interface {
GetSmallerThan(max int) rankedObject
}

type readOnlyCellQueue struct {
grid Grid
cellRefs [DIM * DIM]cellRef
}

type readOnlyCellQueueGetter struct {
queue *readOnlyCellQueue
counter int
}

type finiteQueue struct {
min int
max int
Expand Down Expand Up @@ -87,6 +98,65 @@ func newSyncedFiniteQueue(min int, max int, done chan bool) *syncedFiniteQueue {
return result
}

//defaultRefs should be called to initalize the object to have default refs.
//No need to call this if you're copying in an earlier state.
func (r *readOnlyCellQueue) defaultRefs() {

counter := 0
for row := 0; row < DIM; row++ {
for col := 0; col < DIM; col++ {
r.cellRefs[counter] = cellRef{row, col}
counter++
}
}
}

//Fix should be called after all of the items are in place and before any
//Getters have been vended.
func (r *readOnlyCellQueue) fix() {
sort.Sort(r)
}

func (r *readOnlyCellQueue) Len() int {
return DIM * DIM
}

func (r *readOnlyCellQueue) Less(i, j int) bool {
firstCellRank := r.cellRefs[i].Cell(r.grid).rank()
secondCellRank := r.cellRefs[j].Cell(r.grid).rank()
return firstCellRank < secondCellRank
}

func (r *readOnlyCellQueue) Swap(i, j int) {
r.cellRefs[i], r.cellRefs[j] = r.cellRefs[j], r.cellRefs[i]
}

func (r *readOnlyCellQueue) NewGetter() queueGetter {
return &readOnlyCellQueueGetter{queue: r}
}

func (r *readOnlyCellQueueGetter) Get() rankedObject {
if r.counter >= r.queue.Len() {
return nil
}
result := r.queue.cellRefs[r.counter].Cell(r.queue.grid)
r.counter++
return result
}

func (r *readOnlyCellQueueGetter) GetSmallerThan(max int) rankedObject {
item := r.Get()
if item == nil {
return nil
}
if item.rank() >= max {
//Put it back!
r.counter--
return nil
}
return item
}

func (self *finiteQueueBucket) getItem() rankedObject {

if !self.shuffled {
Expand Down
86 changes: 86 additions & 0 deletions finite_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,92 @@ func (self *SimpleRankedObject) rank() int {
return self._rank
}

func TestReadOnlyCellQueue(t *testing.T) {
grid := NewGrid()
//Load up a realistic grid with realistic ranks for cells.
grid.Load(ADVANCED_TEST_GRID)

queue := readOnlyCellQueue{
grid: grid,
}

queue.defaultRefs()
queue.fix()

getter := queue.NewGetter()

lastRank := 0
counter := 0
item := getter.Get()
for item != nil {

if item.rank() < lastRank {
t.Error("Item", counter, "was smaller than a rank already seen:", item.rank())
}

lastRank = item.rank()

item = getter.Get()

counter++
}

if counter != DIM*DIM {
t.Error("Default getter didn't give us all items")
}

//Make sure a new getter starts at beginning
newGetter := queue.NewGetter()

item = newGetter.Get()

if item == nil {
t.Error("Getting from a new getter gave us nil")
}

item = newGetter.GetSmallerThan(4)

for item != nil {
if item.rank() >= 4 {
t.Error("GetSmallerThan returned too high a rank", item.rank())
}
item = newGetter.GetSmallerThan(4)
}

//Test copying in state from a previous one.

modification := newCellModification(grid.Cell(0, 0))
modification.Number = 5
modifiedGrid := grid.CopyWithModifications(GridModifcation{modification})

newQueue := readOnlyCellQueue{
grid: modifiedGrid,
cellRefs: queue.cellRefs,
}

newQueue.fix()

getter = newQueue.NewGetter()

item = getter.Get()
counter = 0
lastRank = 0
for item != nil {

if item.rank() < lastRank {
t.Error("In new getter got an out-of-rank item")
}
lastRank = item.rank()
counter++
item = getter.Get()
}

if counter != DIM*DIM {
t.Error("New getter returned too early:", counter)
}

}

func TestFiniteQueue(t *testing.T) {
queue := newFiniteQueue(1, DIM)
if queue == nil {
Expand Down
4 changes: 0 additions & 4 deletions grid_modification.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ type CellModification struct {
MarksChanges map[int]bool
}

//TODO: make an immutableQueue, which is just a list of pointers, with a fix()
//method that does a one-time sort before the first thing is called. Getters
//are just an index into the static queue.

//TOOD: make readOnlyCellImpl. Test if neighbors should be derived or not. Can
//burn excludes and impossibles into one array. Everything should be actual
//contiguous memory, no pointers.
Expand Down

0 comments on commit 7c40d90

Please sign in to comment.