module Apps.Sudoku.Validator;

import Anoma.Prelude open;
import Data.ByteString open;

import Apps.Sudoku.Grid open public;
import Apps.Sudoku.Extra open;

--- Check that the number of rows equals the number of columns
square? {A : Type} : List (List A) -> Bool
  | nil := true
  | rows@(r :: rs) := allEq (map length rows) && length r == length rows;

entryFilled? (x : Nat) : Bool := x > 0;

allFilled? : List Nat -> Bool := null  filter (not  entryFilled?);

--- Check that there are no duplicate filled entries
noDuplicates? : List Nat -> Bool := not  hasDuplicates  filter entryFilled?;

--- Check that a subgrid satisfies the Sudoku constraints
validSubGrid? : SubGrid -> Bool
  | s@(subGrid rows) :=
    let
      entries : List Nat := subGridEntries s;
    in square? rows
      && noDuplicates? (subGridEntries s)
      && all λ {x := x < length entries + 1} entries;

--- Check that a subgrid is complete. i.e it satisfies the Sudoku constraints
--- and all of its entries are filled
completeSubGrid? (sg : SubGrid) : Bool :=
  validSubGrid? sg && allFilled? (subGridEntries sg);

--- Check that a grid satisfies the Sudoku constraints
validGrid? : Grid -> Bool
  | g@(grid subGridRows) :=
    let
      subGrids : List SubGrid := flatten subGridRows;
      rows : List (List Nat) := gridRows g;
      columns : List (List Nat) := transpose rows;
    in all validSubGrid? subGrids
      && square? subGridRows
      && all noDuplicates? rows
      && all noDuplicates? columns;

--- Check that a grid is complete. i.e it satisfies the Sudoku constraints
--- and all of its entries are filled
completeGrid? (g : Grid) : Bool := validGrid? g && allFilled? (gridEntries g);
Last modified on 2023-12-07 10:36 UTC