A Latin Square is a $n\times n$ matrix with entries in $\{1,\ldots,n\}$ such that
- each column has the entries $\{1,\ldots,n\}$ and
- each row has the entires $\{1,\ldots,n\}$.
It's a common math problem to "fill in" missing entries of a partial (claimed) Latin Square. I want to write a function whose input is a partially filled $n\times n$ matrix which outputs a valid Latin Square supermatrix if one exists. For instance,
7 1 4 3 2 5 6
4 3 7 6 5 2 1
1 2 6 7 4 3 5
are the first three rows of many valid $7\times7$ Latin Squares. The Null
s in the following $6\times6$ matrix can be replaced with numbers from 4 to 6 which make it a Latin Square
partmat={{,2,3,,,1},{2,3,,,1,},{3,,2,1,,},{,,1,2,,3},{,1,,,3,2},{1,,,3,2,}}
etc. If no values are given, there is a huge amount of solutions. But given some partially filled in matrix (say, with Null
s), write some code to compute a valid coinciding Latin Square, and then find them all.
For the first example, I defined a function
allvalidnextrows[pancakerect_, n_] :=
Select[Flatten[Outer @@
Prepend[Complement[Range@7, #] & /@ (pancakerect\[Transpose]),
List], n - 1], Sort@# == Range@n &]
and used (with rows
appropriately defined)
Nest[DeleteDuplicates[Join @@ ((mat \[Function]
Append[mat, #] & /@ allvalidnextrows[mat, 7]) /@ #)] &, {rows}, 4]
to find the ~11 thousand supmatrices. For the second example, I wrote a weird function which substitutes the 18 missing values
matfunc = Evaluate[Activate@
Fold[{ReplacePart[#[[1]], #2 -> Inactive[Slot][#[[2]]]], #[[2]] +
1} &, {partmat, 1}, Position[partmat, Null]][[1]]] &
and then did some things I'm ashamed of to arrive at
MatrixForm[matfunc @@ Join @@ #] & /@
Flatten[Table[
If[{4, 5, 6} == Sort@{i1[[1]], i4[[1]], i5[[1]]} ==
Sort@{i3[[1]], i4[[2]], i6[[1]]} ==
Sort@{i2[[1]], i5[[2]], i6[[2]]} ==
Sort@{i1[[2]], i2[[2]], i5[[3]]} ==
Sort@{i1[[3]], i3[[2]], i4[[3]]} ==
Sort@{i2[[3]], i3[[3]], i6[[3]]}, {i1, i2, i3, i4, i5, i6},
Nothing], {i1, {{4, 5, 6}, {4, 6, 5}, {5, 4, 6}, {5, 6, 4}, {6, 4,
5}, {6, 5, 4}}}, {i2, {{4, 5, 6}, {4, 6, 5}, {5, 4, 6}, {5, 6,
4}, {6, 4, 5}, {6, 5, 4}}}, {i3, {{4, 5, 6}, {4, 6, 5}, {5, 4,
6}, {5, 6, 4}, {6, 4, 5}, {6, 5, 4}}}, {i4, {{4, 5, 6}, {4, 6,
5}, {5, 4, 6}, {5, 6, 4}, {6, 4, 5}, {6, 5, 4}}}, {i5, {{4, 5,
6}, {4, 6, 5}, {5, 4, 6}, {5, 6, 4}, {6, 4, 5}, {6, 5,
4}}}, {i6, {{4, 5, 6}, {4, 6, 5}, {5, 4, 6}, {5, 6, 4}, {6, 4,
5}, {6, 5, 4}}}], 5]
which yields 72 supmatrices.
This question is to give context to another one, Activating part without resolving [[1]]. I'm curious about generality (I haven't achieved that with my code) and performance (I certainly haven't achieved that with my code).