Message Boards Message Boards

Sudoku & Mathematica - Part I Visualization

A quick search on GitGub shows more than 20k repositories for the query "sudoku".

There are many Mathematica packages that attempt to solve a Sudoku. But, many of those approaches don't fully utilize all Mathematica capabilities. In special: Pattern Matching and Boxes.

Boxes are a very useful concept since it helps us build custom notation. See for example Dirac's Bra-Ket notation and Einstein "summation" notation. Although simple "notations" per se, they have helped gain further insight and made things clearly easier.

Since Mathematica has this 2D-input functionality, we should use it, thus making the code and experience less clunky.

In this Part I, I'll show how to easily create this new notation using MakeBoxes. The Notebook to follow along is attached.

We'll first create two functions: SudokuMatrixQ and SudokuMaskQ, that tests if a given sudoku-matrix/mask is valid, where a mask is a matrix that separates the grid into groups, which will be shown later.

SudokuMatrixQ[square:{{__Integer}..}] := (SquareMatrixQ@square) && (Min@square >= 0) && (Max@square <= Length@square)
SudokuMatrixQ[___] := False
SudokuMaskQ[mask:{{0..}..}] := SquareMatrixQ@mask
SudokuMaskQ[mask_?SudokuMatrixQ] := Function[list,
    (* The masked elements need to be equal-sized *)
    Equal[##1, Length@mask] & @@ MinMax@list
][
    (* The number of times a element appears *)
    Last /@ Tally@DeleteCases[Flatten@mask, 0]
]
SudokuMaskQ[___] := False

Since in StandardForm, matrices are now shown as matrices, but rather as 1D input. Let's fix this:

Sudoku /: MakeBoxes[Sudoku[square_?SudokuMatrixQ, mask_?SudokuMaskQ], StandardForm] := Module[{gridBox},
    gridBox = RowBox@{"(", GridBox@#, ")"} &;
    TemplateBox[{
       gridBox@Map[ToBoxes, square, {2}],
       gridBox@Map[ToBoxes, mask, {2}]
    }, "Sudoku",
       DisplayFunction :> (RowBox@{"Sudoku", "[", #1, "]"} &),
       InterpretationFunction :> (RowBox@{"Sudoku", "[", RowBox@{#1, ",", #2}, "]"} &),
       Tooltip -> Automatic
    ]
]

Sudoku1

Where the contents of the matrix can be editable and the mask-matrix is hidden, for visualization purposes.

Sudoku /: MakeBoxes[Sudoku[square_?SudokuMatrixQ, mask_?SudokuMaskQ], TraditionalForm] := Module[{n = Length@square, pos},
    TemplateBox[{GridBox[
       Map[ToBoxes, square, {2}] /. "0" -> StyleBox["\[CenterDot]", GrayLevel[0.65]],
       GridBoxAlignment -> {"Columns" -> {{Center}}, "Rows" -> {{Center}}},
       GridBoxFrame -> {"ColumnsIndexed" -> {{{1, -1}, {1, -1}} -> True}},
       GridBoxItemSize -> {}, ColumnsEqual -> True, RowsEqual -> True,
       GridBoxBackground -> {"Columns" -> {{GrayLevel[0.9]}}, "Rows" -> {{GrayLevel[0.9]}}, 
         "ItemsIndexed" -> Flatten@Table[pos = Position[mask, i];
         If[Length@pos == 0, Nothing, 
          Thread[pos -> Opacity[0.7, Blend[{RGBColor[0.43, 0.98, 1], RGBColor[ 0.73, 0.89, 0.42],
              RGBColor[1, 0.57, 0.33], RGBColor[0.69, 0.54, 0.80]}, (i - 1)/(n - 1)]]]]
         , {i, n}]}],
         ToBoxes@square,
         ToBoxes@mask
       }, "Sudoku",
       DisplayFunction :> (#1 &),
       InterpretationFunction :> (RowBox@{"Sudoku", "[", RowBox@{#2, ",", #3}, "]"} &),
       Editable -> False, Selectable -> False, Tooltip -> Automatic
    ]
]

Sudoku2

Which gives a very nice representation of the puzzle for arbitrary masks.

Attachments:
POSTED BY: Thales Fernandes
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract