Update gotak import path to fix Travis build
Update import path in the gotak subdir so that Travis tests can be played
against the Github repository.
Also, add missing dependencies to the Travis YAML file.
// Copyright (C) 2016 Mikael Berthe <mikael@lilotux.net>. All rights reserved.
// Use of this source code is governed by the MIT license,
// which can be found in the LICENSE file.
package takuzu
// This file contains the takuzu validation functions and methods.
// checkRange returns true if the range is completely defined, and an error
// if it doesn't follow the rules for a takuzu line or column
// Note that the boolean might be invalid if the error is not nil.
func checkRange(cells []Cell) (bool, error) {
full := true
size := len(cells)
counters := []int{0, 0}
var prevCell Cell
var prevCellCount int
for _, c := range cells {
if !c.Defined {
full = false
prevCell.Defined = false
prevCellCount = 0
continue
}
counters[c.Value]++
if prevCellCount == 0 {
prevCellCount = 1
} else {
if c.Value == prevCell.Value {
prevCellCount++
if prevCellCount > 2 {
v := c.Value
return full, validationError{
ErrorType: ErrorTooManyAdjacentValues,
CellValue: &v,
}
}
} else {
prevCellCount = 1
}
}
prevCell = c
}
if counters[0] > size/2 {
v := 0
return full, validationError{
ErrorType: ErrorTooManyValues,
CellValue: &v,
}
}
if counters[1] > size/2 {
v := 1
return full, validationError{
ErrorType: ErrorTooManyValues,
CellValue: &v,
}
}
return full, nil
}
// CheckRangeCounts returns true if all cells of the provided range are defined,
// as well as the number of 0s and the number of 1s in the range.
func CheckRangeCounts(cells []Cell) (full bool, n0, n1 int) {
counters := []int{0, 0}
full = true
for _, c := range cells {
if c.Defined {
counters[c.Value]++
} else {
full = false
}
}
return full, counters[0], counters[1]
}
// CheckLine returns an error if the line i fails validation
func (b Takuzu) CheckLine(i int) error {
_, err := checkRange(b.GetLine(i))
return err
}
// CheckColumn returns an error if the column i fails validation
func (b Takuzu) CheckColumn(i int) error {
_, err := checkRange(b.GetColumn(i))
return err
}
// Validate checks a whole board for errors (not completeness)
// Returns true if all cells are defined.
func (b Takuzu) Validate() (bool, error) {
finished := true
computeVal := func(cells []Cell) (val int) {
for i := 0; i < len(cells); i++ {
val += cells[i].Value * 1 << uint(i)
}
return
}
lineVals := make(map[int]bool)
colVals := make(map[int]bool)
for i := 0; i < b.Size; i++ {
var d []Cell
var full bool
var err error
// Let's check line i
d = b.GetLine(i)
full, err = checkRange(d)
if err != nil {
err := err.(validationError)
err.LineNumber = &i
return false, err
}
if full {
hv := computeVal(d)
if lineVals[hv] {
err := validationError{
ErrorType: ErrorDuplicate,
LineNumber: &i,
}
return false, err
}
lineVals[hv] = true
} else {
finished = false
}
// Let's check column i
d = b.GetColumn(i)
full, err = checkRange(d)
if err != nil {
err := err.(validationError)
err.ColumnNumber = &i
return false, err
}
if full {
hv := computeVal(d)
if colVals[hv] {
err := validationError{
ErrorType: ErrorDuplicate,
ColumnNumber: &i,
}
return false, err
}
colVals[hv] = true
} else {
finished = false
}
}
return finished, nil
}