254 for i := range b.Board { |
254 for i := range b.Board { |
255 dumpRange(b.Board[i]) |
255 dumpRange(b.Board[i]) |
256 } |
256 } |
257 } |
257 } |
258 |
258 |
259 // CheckLine returns an error if the line i fails validation |
|
260 func (b Takuzu) CheckLine(i int) error { |
|
261 _, err := checkRange(b.GetLine(i)) |
|
262 return err |
|
263 } |
|
264 |
|
265 // CheckColumn returns an error if the column i fails validation |
|
266 func (b Takuzu) CheckColumn(i int) error { |
|
267 _, err := checkRange(b.GetColumn(i)) |
|
268 return err |
|
269 } |
|
270 |
|
271 // Validate checks a whole board for errors (not completeness) |
|
272 // Returns true if all cells are defined. |
|
273 func (b Takuzu) Validate() (bool, error) { |
|
274 finished := true |
|
275 |
|
276 computeVal := func(cells []Cell) (val int) { |
|
277 for i := 0; i < len(cells); i++ { |
|
278 val += cells[i].Value * 1 << uint(i) |
|
279 } |
|
280 return |
|
281 } |
|
282 |
|
283 lineVals := make(map[int]bool) |
|
284 colVals := make(map[int]bool) |
|
285 |
|
286 for i := 0; i < b.Size; i++ { |
|
287 var d []Cell |
|
288 var full bool |
|
289 var err error |
|
290 |
|
291 // Let's check line i |
|
292 d = b.GetLine(i) |
|
293 full, err = checkRange(d) |
|
294 if err != nil { |
|
295 return false, errors.Wrapf(err, "line %d", i) |
|
296 } |
|
297 if full { |
|
298 hv := computeVal(d) |
|
299 if lineVals[hv] { |
|
300 return false, fmt.Errorf("duplicate lines (%d)", i) |
|
301 } |
|
302 lineVals[hv] = true |
|
303 } else { |
|
304 finished = false |
|
305 } |
|
306 |
|
307 // Let's check column i |
|
308 d = b.GetColumn(i) |
|
309 full, err = checkRange(d) |
|
310 if err != nil { |
|
311 return false, errors.Wrapf(err, "column %d", i) |
|
312 } |
|
313 if full { |
|
314 hv := computeVal(d) |
|
315 if colVals[hv] { |
|
316 return false, fmt.Errorf("duplicate columns (%d)", i) |
|
317 } |
|
318 colVals[hv] = true |
|
319 } else { |
|
320 finished = false |
|
321 } |
|
322 } |
|
323 return finished, nil |
|
324 } |
|
325 |
|
326 func dumpRange(cells []Cell) { |
259 func dumpRange(cells []Cell) { |
327 for _, c := range cells { |
260 for _, c := range cells { |
328 if !c.Defined { |
261 if !c.Defined { |
329 fmt.Printf(". ") |
262 fmt.Printf(". ") |
330 continue |
263 continue |
331 } |
264 } |
332 fmt.Printf("%d ", c.Value) |
265 fmt.Printf("%d ", c.Value) |
333 } |
266 } |
334 fmt.Println() |
267 fmt.Println() |
335 } |
268 } |
336 |
|
337 // checkRange returns true if the range is completely defined, and an error |
|
338 // if it doesn't follow the rules for a takuzu line or column |
|
339 // Note that the boolean might be invalid if the error is not nil. |
|
340 func checkRange(cells []Cell) (bool, error) { |
|
341 full := true |
|
342 size := len(cells) |
|
343 counters := []int{0, 0} |
|
344 |
|
345 var prevCell Cell |
|
346 var prevCellCount int |
|
347 |
|
348 for _, c := range cells { |
|
349 if !c.Defined { |
|
350 full = false |
|
351 prevCell.Defined = false |
|
352 prevCellCount = 0 |
|
353 continue |
|
354 } |
|
355 counters[c.Value]++ |
|
356 if prevCellCount == 0 { |
|
357 prevCellCount = 1 |
|
358 } else { |
|
359 if c.Value == prevCell.Value { |
|
360 prevCellCount++ |
|
361 if prevCellCount > 2 { |
|
362 return full, errors.Errorf("3+ same values %d", c.Value) |
|
363 } |
|
364 } else { |
|
365 prevCellCount = 1 |
|
366 } |
|
367 |
|
368 } |
|
369 prevCell = c |
|
370 } |
|
371 if counters[0] > size/2 { |
|
372 return full, errors.Errorf("too many zeroes") |
|
373 } |
|
374 if counters[1] > size/2 { |
|
375 return full, errors.Errorf("too many ones") |
|
376 } |
|
377 return full, nil |
|
378 } |
|
379 |
|
380 // CheckRangeCounts returns true if all cells of the provided range are defined, |
|
381 // as well as the number of 0s and the number of 1s in the range. |
|
382 func CheckRangeCounts(cells []Cell) (full bool, n0, n1 int) { |
|
383 counters := []int{0, 0} |
|
384 full = true |
|
385 |
|
386 for _, c := range cells { |
|
387 if c.Defined { |
|
388 counters[c.Value]++ |
|
389 } else { |
|
390 full = false |
|
391 } |
|
392 } |
|
393 return full, counters[0], counters[1] |
|
394 } |
|