--- a/takuzu.go Sun Oct 16 09:48:36 2016 +0200
+++ b/takuzu.go Sun Oct 16 10:08:11 2016 +0200
@@ -256,73 +256,6 @@
}
}
-// 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 {
- return false, errors.Wrapf(err, "line %d", i)
- }
- if full {
- hv := computeVal(d)
- if lineVals[hv] {
- return false, fmt.Errorf("duplicate lines (%d)", i)
- }
- lineVals[hv] = true
- } else {
- finished = false
- }
-
- // Let's check column i
- d = b.GetColumn(i)
- full, err = checkRange(d)
- if err != nil {
- return false, errors.Wrapf(err, "column %d", i)
- }
- if full {
- hv := computeVal(d)
- if colVals[hv] {
- return false, fmt.Errorf("duplicate columns (%d)", i)
- }
- colVals[hv] = true
- } else {
- finished = false
- }
- }
- return finished, nil
-}
-
func dumpRange(cells []Cell) {
for _, c := range cells {
if !c.Defined {
@@ -333,62 +266,3 @@
}
fmt.Println()
}
-
-// 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 {
- return full, errors.Errorf("3+ same values %d", c.Value)
- }
- } else {
- prevCellCount = 1
- }
-
- }
- prevCell = c
- }
- if counters[0] > size/2 {
- return full, errors.Errorf("too many zeroes")
- }
- if counters[1] > size/2 {
- return full, errors.Errorf("too many ones")
- }
- 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]
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/validate.go Sun Oct 16 10:08:11 2016 +0200
@@ -0,0 +1,133 @@
+package takuzu
+
+import (
+ "fmt"
+
+ "github.com/pkg/errors"
+)
+
+// 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 {
+ return full, errors.Errorf("3+ same values %d", c.Value)
+ }
+ } else {
+ prevCellCount = 1
+ }
+
+ }
+ prevCell = c
+ }
+ if counters[0] > size/2 {
+ return full, errors.Errorf("too many zeroes")
+ }
+ if counters[1] > size/2 {
+ return full, errors.Errorf("too many ones")
+ }
+ 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 {
+ return false, errors.Wrapf(err, "line %d", i)
+ }
+ if full {
+ hv := computeVal(d)
+ if lineVals[hv] {
+ return false, fmt.Errorf("duplicate lines (%d)", i)
+ }
+ lineVals[hv] = true
+ } else {
+ finished = false
+ }
+
+ // Let's check column i
+ d = b.GetColumn(i)
+ full, err = checkRange(d)
+ if err != nil {
+ return false, errors.Wrapf(err, "column %d", i)
+ }
+ if full {
+ hv := computeVal(d)
+ if colVals[hv] {
+ return false, fmt.Errorf("duplicate columns (%d)", i)
+ }
+ colVals[hv] = true
+ } else {
+ finished = false
+ }
+ }
+ return finished, nil
+}