summaryrefslogtreecommitdiff
path: root/macros/context
diff options
context:
space:
mode:
Diffstat (limited to 'macros/context')
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/LICENSE21
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/README.md40
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/VERSION1
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-01.txt9
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-02.txt9
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-03.txt9
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.lua1237
-rw-r--r--macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.mkvi217
8 files changed, 1543 insertions, 0 deletions
diff --git a/macros/context/contrib/context-sudoku/sudoku/LICENSE b/macros/context/contrib/context-sudoku/sudoku/LICENSE
new file mode 100644
index 0000000000..ab4635fd09
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021-2023 Jairo A. del Rio
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/macros/context/contrib/context-sudoku/sudoku/README.md b/macros/context/contrib/context-sudoku/sudoku/README.md
new file mode 100644
index 0000000000..f9ffa7b04e
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/README.md
@@ -0,0 +1,40 @@
+# sudoku
+
+This is a ConTeXt port of a famous sudoku solver by Peter Norvig. It
+provides four commands, as well as a command handler:
+
+1. `\sudoku` typesets a sudoku if valid.
+2. `\sudokufile` typesets a sudoku from a file if valid.
+3. `\solvesudoku` solves a sudoku if valid.
+3. `\solvesudokufile` solves a sudoku from a file if valid.
+5. `\setupsudoku` is the command handler for commands above.
+
+`\setupsudoku` understands the following parameters:
+
+```tex
+\setupsudoku
+ [size=2em,
+ align={middle,lohi},
+ evenbackground=color,
+ oddbackground=color,
+ evenbackgroundcolor=darkred,
+ oddbackgroundcolor=darkblue]
+```
+
+As you might notice, sudokus are just `TABLE`'s in disguise, but only
+certain parameters are passed in order to enforce constraints and keep
+a sudoku in square shape.
+
+If an invalid sudoku or sudoku file is provided, a placeholder with an
+error message is printed instead. To change message errors, set
+something like this:
+
+```tex
+\setupsudoku
+ [placeholdercommand=\inframed,
+ placeholderlabela=First error,
+ placeholderlabelb=Second error,
+ placeholderlabelc=Third error]
+```
+
+For actual examples, check `t-sudoku.mkvi`.
diff --git a/macros/context/contrib/context-sudoku/sudoku/VERSION b/macros/context/contrib/context-sudoku/sudoku/VERSION
new file mode 100644
index 0000000000..0129129226
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/VERSION
@@ -0,0 +1 @@
+2023-05-15
diff --git a/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-01.txt b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-01.txt
new file mode 100644
index 0000000000..457b024636
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-01.txt
@@ -0,0 +1,9 @@
+003 010 008
+000 400 030
+870 003 020
+010 009 605
+300 867 002
+906 500 040
+020 900 074
+090 006 000
+500 070 100 \ No newline at end of file
diff --git a/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-02.txt b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-02.txt
new file mode 100644
index 0000000000..9898c3f46b
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-02.txt
@@ -0,0 +1,9 @@
+000 000 620
+106 230 040
+900 600 001
+200 400 803
+090 000 010
+708 009 004
+600 005 008
+020 048 905
+045 000 000
diff --git a/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-03.txt b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-03.txt
new file mode 100644
index 0000000000..05e95666b6
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku-test-03.txt
@@ -0,0 +1,9 @@
+043080250
+600000000
+000001094
+900004070
+000608000
+010200003
+820500000
+000000005
+034090710
diff --git a/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.lua b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.lua
new file mode 100644
index 0000000000..4e6e12578b
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.lua
@@ -0,0 +1,1237 @@
+if not modules then modules = { } end modules ['t-sudoku'] =
+{
+ version = "2023-05-15",
+ comment = "Sudokus for ConTeXt",
+ author = "Jairo A. del Rio",
+ copyright = "Jairo A. del Rio",
+ license = "MIT License"
+}
+
+-- Sources:
+
+-- https://norvig.com/sudoku.html
+-- https://naokishibuya.medium.com/peter-norvigs-sudoku-solver-25779bb349ce
+-- https://gist.github.com/neilalbrock/894520
+
+local table, math, io = table, math, io
+local ipairs, pairs, tostring = ipairs, pairs, tostring
+
+local floor, ceil = math.floor, math.ceil
+local insert, concat, sort = table.insert, table.concat, table.sort
+
+-- ConTeXt goodies
+
+local context = context
+local interfaces = interfaces
+local implement = interfaces.implement
+
+-- Take a look for definitions
+-- https://source.contextgarden.net/tex/context/base/mkiv/l-table.lua
+-- https://source.contextgarden.net/tex/context/base/mkiv/l-io.lua
+
+local contains, copy, unique = table.contains, table.copy, table.unique
+
+local loaddata = io.loaddata
+
+local rows = {"A", "B", "C", "D", "E", "F", "G", "H", "I"}
+local columns = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}
+
+local rowsquare =
+{
+ {"A", "B", "C"}, {"D", "E", "F"}, {"G", "H", "I"}
+}
+
+local columnsquare =
+{
+ {"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}
+}
+
+local digits = '123456789'
+
+-- Helper functions
+-- F#ck Python
+
+local shuffle, string_to_table
+
+shuffle = function(t)
+ for i = #t, 2, -1 do
+ local j = random(i)
+ t[i], t[j] = t[j], t[i]
+ end
+ return t
+end
+
+string_to_table = function(s)
+ local result = {}
+ s = s:gsub("[.%d]", function(x)
+ insert(result, x == "." and x or tostring(floor(x)))
+ end)
+ return result
+end
+
+-- Data
+
+local squares, units
+
+squares =
+{
+ "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
+ "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9",
+ "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9",
+ "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9",
+ "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9",
+ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9",
+ "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9",
+ "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9",
+ "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8", "I9"
+}
+
+units =
+{
+ ['A1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['A2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['A3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['A4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['A5'] = {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['A6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['A7'] = {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['A8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['A9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['B1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['B2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['B3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['B4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['B5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['B6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['B7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['B8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['B9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['C1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['C2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['C3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'}
+ },
+ ['C4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['C5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['C6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6'}
+ },
+ ['C7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['C8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['C9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'},
+ {'A7', 'A8', 'A9', 'B7', 'B8', 'B9', 'C7', 'C8', 'C9'}
+ },
+ ['D1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['D2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['D3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['D4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['D5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['D6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['D7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['D8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['D9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['E1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['E2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['E3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['E4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['E5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['E6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['E7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['E8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['E9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['F1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['F2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['F3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D1', 'D2', 'D3', 'E1', 'E2', 'E3', 'F1', 'F2', 'F3'}
+ },
+ ['F4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['F5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['F6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D4', 'D5', 'D6', 'E4', 'E5', 'E6', 'F4', 'F5', 'F6'}
+ },
+ ['F7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['F8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['F9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9'},
+ {'D7', 'D8', 'D9', 'E7', 'E8', 'E9', 'F7', 'F8', 'F9'}
+ },
+ ['G1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['G2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['G3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['G4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['G5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['G6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['G7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['G8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['G9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['H1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['H2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['H3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['H4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['H5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['H6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['H7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['H8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['H9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['I1'] =
+ {
+ {'A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['I2'] =
+ {
+ {'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['I3'] =
+ {
+ {'A3', 'B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G1', 'G2', 'G3', 'H1', 'H2', 'H3', 'I1', 'I2', 'I3'}
+ },
+ ['I4'] =
+ {
+ {'A4', 'B4', 'C4', 'D4', 'E4', 'F4', 'G4', 'H4', 'I4'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['I5'] =
+ {
+ {'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'H5', 'I5'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['I6'] =
+ {
+ {'A6', 'B6', 'C6', 'D6', 'E6', 'F6', 'G6', 'H6', 'I6'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G4', 'G5', 'G6', 'H4', 'H5', 'H6', 'I4', 'I5', 'I6'}
+ },
+ ['I7'] =
+ {
+ {'A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7', 'I7'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['I8'] =
+ {
+ {'A8', 'B8', 'C8', 'D8', 'E8', 'F8', 'G8', 'H8', 'I8'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ },
+ ['I9'] =
+ {
+ {'A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'},
+ {'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'},
+ {'G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9'}
+ }
+}
+
+local peers =
+{
+ ['A1'] =
+ {
+ 'C1', 'A5', 'A4', 'H1', 'A9', 'D1', 'E1', 'A7', 'A2', 'F1',
+ 'B3', 'B1', 'G1', 'I1', 'C3', 'B2', 'A6', 'A3', 'A8', 'C2'
+ },
+ ['A2'] =
+ {
+ 'C1', 'A5', 'A4', 'A9', 'I2', 'A7', 'F2', 'B3', 'H2', 'D2',
+ 'B1', 'E2', 'C3', 'B2', 'A6', 'A1', 'A3', 'A8', 'C2', 'G2'
+ },
+ ['A3'] =
+ {
+ 'C1', 'A5', 'A4', 'A9', 'I3', 'F3', 'D3', 'A7', 'A2', 'B3',
+ 'B1', 'E3', 'C3', 'H3', 'B2', 'G3', 'A6', 'A1', 'A8', 'C2'
+ },
+ ['A4'] =
+ {
+ 'A5', 'A9', 'H4', 'I4', 'A7', 'A2', 'A8', 'C4', 'B6', 'C5',
+ 'C6', 'B5', 'A6', 'D4', 'G4', 'A1', 'E4', 'A3', 'F4', 'B4'
+ },
+ ['A5'] =
+ {
+ 'A4', 'A9', 'H5', 'A7', 'A2', 'D5', 'C4', 'E5', 'F5', 'B6',
+ 'C5', 'C6', 'B5', 'I5', 'A6', 'A1', 'A3', 'A8', 'G5', 'B4'
+ },
+ ['A6'] =
+ {
+ 'A5', 'A4', 'A9', 'F6', 'G6', 'D6', 'I6', 'A2', 'A7', 'E6',
+ 'H6', 'C4', 'B6', 'C6', 'C5', 'B5', 'A1', 'A3', 'A8', 'B4'
+ },
+ ['A7'] =
+ {
+ 'B7', 'A4', 'A9', 'A5', 'C9', 'C7', 'E7', 'A2', 'F7', 'B9',
+ 'D7', 'G7', 'I7', 'A6', 'C8', 'A1', 'A3', 'A8', 'B8', 'H7'
+ },
+ ['A8'] =
+ {
+ 'A5', 'A4', 'A9', 'E8', 'F8', 'B7', 'C9', 'C7', 'A7', 'A2',
+ 'B9', 'I8', 'H8', 'A6', 'C8', 'A1', 'A3', 'B8', 'G8', 'D8'
+ },
+ ['A9'] =
+ {
+ 'A5', 'A4', 'B7', 'E9', 'C9', 'I9', 'C7', 'H9', 'A7', 'A2',
+ 'F9', 'B9', 'G9', 'D9', 'A6', 'C8', 'A1', 'A3', 'A8', 'B8'
+ },
+ ['B1'] =
+ {
+ 'C1', 'B7', 'H1', 'D1', 'E1', 'A2', 'F1', 'B3', 'B9', 'G1',
+ 'B6', 'I1', 'C3', 'B2', 'B5', 'A1', 'A3', 'B8', 'C2', 'B4'
+ },
+ ['B2'] =
+ {
+ 'C1', 'B7', 'I2', 'F2', 'A2', 'B3', 'H2', 'D2', 'B1', 'B9',
+ 'B6', 'E2', 'C3', 'B5', 'A1', 'A3', 'B8', 'C2', 'G2', 'B4'
+ },
+ ['B3'] =
+ {
+ 'C1', 'B7', 'I3', 'F3', 'D3', 'A2', 'B1', 'B9', 'B6', 'E3',
+ 'C3', 'H3', 'B2', 'B5', 'G3', 'A1', 'A3', 'B8', 'C2', 'B4'
+ },
+ ['B4'] =
+ {
+ 'B7', 'A4', 'A5', 'H4', 'I4', 'B3', 'C4', 'B1', 'B9', 'B6',
+ 'C5', 'C6', 'B2', 'B5', 'A6', 'D4', 'G4', 'E4', 'B8', 'F4'
+ },
+ ['B5'] =
+ {
+ 'A5', 'B7', 'A4', 'H5', 'B3', 'D5', 'C4', 'B1', 'B9', 'F5',
+ 'E5', 'B6', 'C5', 'C6', 'B2', 'I5', 'A6', 'B8', 'G5', 'B4'
+ },
+ ['B6'] =
+ {
+ 'B7', 'A4', 'A5', 'F6', 'G6', 'D6', 'I6', 'B3', 'E6', 'H6',
+ 'C4', 'B1', 'B9', 'C6', 'C5', 'B2', 'B5', 'A6', 'B8', 'B4'
+ },
+ ['B7'] =
+ {
+ 'A9', 'C9', 'C7', 'E7', 'A7', 'A8', 'B3', 'B1', 'B9', 'D7',
+ 'G7', 'B6', 'I7', 'B2', 'B5', 'C8', 'F7', 'B8', 'H7', 'B4'
+ },
+ ['B8'] =
+ {
+ 'B7', 'A9', 'E8', 'F8', 'C9', 'C7', 'A7', 'B3', 'B1', 'B9',
+ 'B6', 'I8', 'B2', 'H8', 'B5', 'C8', 'A8', 'G8', 'D8', 'B4'
+ },
+ ['B9'] =
+ {
+ 'B7', 'A9', 'E9', 'C9', 'I9', 'C7', 'H9', 'A7', 'B3', 'F9',
+ 'B1', 'B6', 'G9', 'D9', 'B2', 'B5', 'C8', 'A8', 'B8', 'B4'
+ },
+ ['C1'] =
+ {
+ 'H1', 'D1', 'E1', 'C9', 'C7', 'A2', 'F1', 'B3', 'B1', 'G1',
+ 'C5', 'I1', 'C3', 'C6', 'B2', 'C8', 'A1', 'A3', 'C2', 'C4'
+ },
+ ['C2'] =
+ {
+ 'C1', 'C9', 'C7', 'I2', 'F2', 'A2', 'B3', 'H2', 'D2', 'B1',
+ 'E2', 'C5', 'C6', 'C3', 'B2', 'C8', 'A1', 'A3', 'G2', 'C4'
+ },
+ ['C3'] =
+ {
+ 'C1', 'C9', 'I3', 'C7', 'F3', 'D3', 'A2', 'B3', 'B1', 'E3',
+ 'C5', 'C6', 'H3', 'B2', 'G3', 'C8', 'A1', 'A3', 'C2', 'C4'
+ },
+ ['C4'] =
+ {
+ 'C1', 'A5', 'A4', 'H4', 'C9', 'I4', 'C7', 'B6', 'C5', 'C6',
+ 'C3', 'B5', 'A6', 'C8', 'D4', 'G4', 'E4', 'C2', 'F4', 'B4'
+ },
+ ['C5'] =
+ {
+ 'C1', 'A5', 'A4', 'C9', 'H5', 'C7', 'D5', 'E5', 'F5', 'B4',
+ 'B6', 'C6', 'C3', 'B5', 'I5', 'A6', 'C8', 'C2', 'G5', 'C4'
+ },
+ ['C6'] =
+ {
+ 'C1', 'A5', 'A4', 'C9', 'C7', 'F6', 'G6', 'D6', 'I6', 'E6',
+ 'H6', 'B4', 'B6', 'C5', 'C3', 'B5', 'A6', 'C8', 'C2', 'C4'
+ },
+ ['C7'] =
+ {
+ 'C1', 'B7', 'A9', 'C9', 'E7', 'A7', 'A8', 'B9', 'D7', 'G7',
+ 'C5', 'C6', 'C3', 'I7', 'C8', 'F7', 'B8', 'H7', 'C2', 'C4'
+ },
+ ['C8'] =
+ {
+ 'C1', 'B7', 'A9', 'E8', 'F8', 'C9', 'C7', 'A7', 'B9', 'I8',
+ 'C5', 'C3', 'C6', 'H8', 'A8', 'B8', 'G8', 'C2', 'D8', 'C4'
+ },
+ ['C9'] =
+ {
+ 'C1', 'B7', 'A9', 'E9', 'I9', 'C7', 'H9', 'A7', 'F9', 'B9',
+ 'G9', 'C5', 'C6', 'D9', 'C3', 'C8', 'A8', 'B8', 'C2', 'C4'
+ },
+ ['D1'] =
+ {
+ 'C1', 'H1', 'E1', 'F3', 'D3', 'D6', 'F2', 'F1', 'D5', 'D2',
+ 'B1', 'D7', 'G1', 'E2', 'E3', 'I1', 'D9', 'A1', 'D4', 'D8'
+ },
+ ['D2'] =
+ {
+ 'D1', 'E1', 'F3', 'D3', 'I2', 'D6', 'F2', 'A2', 'F1', 'D5',
+ 'H2', 'D7', 'E2', 'E3', 'D9', 'B2', 'D4', 'C2', 'G2', 'D8'
+ },
+ ['D3'] =
+ {
+ 'D1', 'E1', 'I3', 'F3', 'D6', 'F2', 'F1', 'B3', 'D5', 'D2',
+ 'D7', 'E2', 'E3', 'C3', 'H3', 'D9', 'G3', 'D4', 'A3', 'D8'
+ },
+ ['D4'] =
+ {
+ 'A4', 'H4', 'D1', 'F4', 'I4', 'D3', 'F6', 'D6', 'D5', 'D2',
+ 'E6', 'C4', 'D7', 'F5', 'E5', 'D9', 'G4', 'E4', 'D8', 'B4'
+ },
+ ['D5'] =
+ {
+ 'A5', 'D1', 'F4', 'H5', 'D3', 'F6', 'D6', 'D2', 'E6', 'E5',
+ 'F5', 'D7', 'C5', 'D9', 'B5', 'I5', 'D4', 'E4', 'G5', 'D8'
+ },
+ ['D6'] =
+ {
+ 'D1', 'F4', 'D3', 'F6', 'G6', 'I6', 'D5', 'D2', 'E6', 'H6',
+ 'D7', 'F5', 'E5', 'B6', 'C6', 'D9', 'A6', 'D4', 'E4', 'D8'
+ },
+ ['D7'] =
+ {
+ 'B7', 'E8', 'F8', 'D1', 'E9', 'C7', 'D3', 'E7', 'A7', 'D6',
+ 'D5', 'D2', 'F9', 'G7', 'D9', 'I7', 'D4', 'F7', 'H7', 'D8'
+ },
+ ['D8'] =
+ {
+ 'E8', 'F8', 'D1', 'E9', 'D3', 'E7', 'D6', 'A8', 'D5', 'D2',
+ 'F9', 'D7', 'I8', 'D9', 'H8', 'C8', 'D4', 'F7', 'B8', 'G8'
+ },
+ ['D9'] =
+ {
+ 'A9', 'E8', 'F8', 'D1', 'E9', 'C9', 'I9', 'D3', 'E7', 'H9',
+ 'D6', 'D5', 'D2', 'F9', 'B9', 'D7', 'G9', 'D4', 'F7', 'D8'
+ },
+ ['E1'] =
+ {
+ 'C1', 'H1', 'E8', 'D1', 'E9', 'F3', 'D3', 'E7', 'F2', 'F1',
+ 'D2', 'E6', 'B1', 'E5', 'G1', 'E2', 'E3', 'I1', 'A1', 'E4'
+ },
+ ['E2'] =
+ {
+ 'E8', 'D1', 'E1', 'E9', 'F3', 'D3', 'E7', 'I2', 'F2', 'A2',
+ 'F1', 'H2', 'D2', 'E6', 'E5', 'E3', 'B2', 'E4', 'C2', 'G2'
+ },
+ ['E3'] =
+ {
+ 'E8', 'D1', 'E1', 'I3', 'E9', 'F3', 'D3', 'E7', 'F2', 'F1',
+ 'B3', 'D2', 'E6', 'E5', 'E2', 'C3', 'H3', 'G3', 'A3', 'E4'
+ },
+ ['E4'] =
+ {
+ 'A4', 'E8', 'H4', 'E1', 'E9', 'I4', 'E7', 'F6', 'D6', 'D5',
+ 'E6', 'C4', 'E5', 'F5', 'E2', 'E3', 'D4', 'G4', 'F4', 'B4'
+ },
+ ['E5'] =
+ {
+ 'A5', 'E8', 'E1', 'E9', 'H5', 'E7', 'F6', 'D6', 'D5', 'E6',
+ 'F5', 'E2', 'E3', 'C5', 'B5', 'I5', 'D4', 'E4', 'G5', 'F4'
+ },
+ ['E6'] =
+ {
+ 'E8', 'E1', 'E9', 'E7', 'F6', 'G6', 'D6', 'I6', 'D5', 'H6',
+ 'E5', 'F5', 'B6', 'E2', 'E3', 'C6', 'A6', 'D4', 'E4', 'F4'
+ },
+ ['E7'] =
+ {
+ 'B7', 'E8', 'F8', 'E1', 'E9', 'C7', 'A7', 'F9', 'E6', 'D7',
+ 'E5', 'G7', 'E2', 'E3', 'D9', 'I7', 'E4', 'F7', 'H7', 'D8'
+ },
+ ['E8'] =
+ {
+ 'F8', 'E1', 'E9', 'E7', 'A8', 'F9', 'E6', 'E5', 'D7', 'E2',
+ 'E3', 'I8', 'D9', 'H8', 'C8', 'E4', 'F7', 'B8', 'G8', 'D8'
+ },
+ ['E9'] =
+ {
+ 'A9', 'E8', 'F8', 'C9', 'E1', 'I9', 'E7', 'H9', 'F9', 'E6',
+ 'B9', 'E5', 'D7', 'E2', 'G9', 'E3', 'D9', 'E4', 'F7', 'D8'
+ },
+ ['F1'] =
+ {
+ 'C1', 'H1', 'F8', 'D1', 'E1', 'F3', 'D3', 'F6', 'F2', 'D2',
+ 'F9', 'B1', 'G1', 'F5', 'E2', 'E3', 'I1', 'A1', 'F7', 'F4'
+ },
+ ['F2'] =
+ {
+ 'F8', 'D1', 'E1', 'F3', 'D3', 'I2', 'F6', 'A2', 'F1', 'H2',
+ 'F9', 'D2', 'F5', 'E2', 'E3', 'B2', 'F7', 'C2', 'G2', 'F4'
+ },
+ ['F3'] =
+ {
+ 'F8', 'D1', 'E1', 'I3', 'D3', 'F6', 'F2', 'F1', 'B3', 'D2',
+ 'F9', 'F5', 'E2', 'E3', 'C3', 'H3', 'G3', 'A3', 'F7', 'F4'
+ },
+ ['F4'] =
+ {
+ 'A4', 'F8', 'H4', 'I4', 'F3', 'F6', 'D6', 'F2', 'F7', 'F1',
+ 'D5', 'F9', 'E6', 'C4', 'E5', 'F5', 'D4', 'G4', 'E4', 'B4'
+ },
+ ['F5'] =
+ {
+ 'A5', 'F8', 'H5', 'F3', 'F6', 'D6', 'F2', 'F1', 'D5', 'F9',
+ 'E6', 'E5', 'C5', 'B5', 'I5', 'D4', 'E4', 'F7', 'G5', 'F4'
+ },
+ ['F6'] =
+ {
+ 'F8', 'F3', 'G6', 'D6', 'F2', 'I6', 'F1', 'D5', 'F9', 'E6',
+ 'H6', 'E5', 'F5', 'B6', 'C6', 'A6', 'D4', 'E4', 'F7', 'F4'
+ },
+ ['F7'] =
+ {
+ 'B7', 'E8', 'F8', 'E9', 'F4', 'C7', 'F3', 'E7', 'F6', 'A7',
+ 'F2', 'F1', 'F9', 'D7', 'F5', 'G7', 'D9', 'I7', 'H7', 'D8'
+ },
+ ['F8'] =
+ {
+ 'E8', 'E9', 'F3', 'E7', 'F6', 'F2', 'F7', 'F1', 'F9', 'D7',
+ 'F5', 'D8', 'I8', 'D9', 'H8', 'C8', 'A8', 'B8', 'G8', 'F4'
+ },
+ ['F9'] =
+ {
+ 'A9', 'E8', 'F8', 'E9', 'C9', 'F4', 'I9', 'F3', 'E7', 'F6',
+ 'H9', 'F2', 'F1', 'B9', 'D7', 'F5', 'G9', 'D9', 'F7', 'D8'
+ },
+ ['G1'] =
+ {
+ 'C1', 'H1', 'D1', 'E1', 'I3', 'I2', 'G5', 'G6', 'F1', 'H2',
+ 'B1', 'G7', 'G9', 'I1', 'H3', 'G3', 'A1', 'G4', 'G8', 'G2'
+ },
+ ['G2'] =
+ {
+ 'H1', 'I3', 'I2', 'G5', 'G6', 'F2', 'A2', 'H2', 'D2', 'G1',
+ 'G7', 'E2', 'G9', 'I1', 'H3', 'B2', 'G3', 'G4', 'G8', 'C2'
+ },
+ ['G3'] =
+ {
+ 'H1', 'I3', 'F3', 'D3', 'I2', 'G5', 'G6', 'B3', 'H2', 'G1',
+ 'G7', 'G9', 'E3', 'I1', 'C3', 'H3', 'G4', 'A3', 'G8', 'G2'
+ },
+ ['G4'] =
+ {
+ 'A4', 'H4', 'I4', 'H5', 'G5', 'G6', 'I6', 'H6', 'C4', 'G1',
+ 'G7', 'G9', 'G3', 'I5', 'D4', 'E4', 'G8', 'G2', 'F4', 'B4'
+ },
+ ['G5'] =
+ {
+ 'A5', 'H4', 'I4', 'H5', 'G6', 'I6', 'D5', 'H6', 'G2', 'E5',
+ 'F5', 'G1', 'G7', 'G9', 'C5', 'B5', 'G3', 'I5', 'G4', 'G8'
+ },
+ ['G6'] =
+ {
+ 'H4', 'I4', 'H5', 'G5', 'F6', 'D6', 'I6', 'E6', 'H6', 'G1',
+ 'G7', 'B6', 'G9', 'C6', 'G3', 'I5', 'A6', 'G4', 'G8', 'G2'
+ },
+ ['G7'] =
+ {
+ 'B7', 'C7', 'I9', 'E7', 'G5', 'G6', 'H9', 'A7', 'G8', 'D7',
+ 'G1', 'G9', 'I8', 'I7', 'H8', 'G3', 'G4', 'F7', 'H7', 'G2'
+ },
+ ['G8'] =
+ {
+ 'E8', 'F8', 'I9', 'G5', 'H7', 'G6', 'H9', 'G1', 'G7', 'G9',
+ 'I8', 'I7', 'H8', 'G3', 'C8', 'G4', 'A8', 'B8', 'G2', 'D8'
+ },
+ ['G9'] =
+ {
+ 'A9', 'E9', 'C9', 'I9', 'H7', 'G6', 'H9', 'F9', 'B9', 'G2',
+ 'G1', 'G7', 'I8', 'D9', 'I7', 'H8', 'G3', 'G4', 'G8', 'G5'
+ },
+ ['H1'] =
+ {
+ 'C1', 'H4', 'D1', 'E1', 'I3', 'H5', 'I2', 'H9', 'F1', 'H2',
+ 'H6', 'B1', 'G1', 'I1', 'H3', 'H8', 'G3', 'A1', 'H7', 'G2'
+ },
+ ['H2'] =
+ {
+ 'H1', 'H4', 'I3', 'H5', 'I2', 'H9', 'F2', 'A2', 'D2', 'H6',
+ 'G1', 'E2', 'I1', 'H3', 'H8', 'B2', 'G3', 'H7', 'C2', 'G2'
+ },
+ ['H3'] =
+ {
+ 'H1', 'H4', 'I3', 'H5', 'F3', 'D3', 'I2', 'H9', 'B3', 'H2',
+ 'H6', 'G1', 'E3', 'I1', 'C3', 'H8', 'G3', 'A3', 'H7', 'G2'
+ },
+ ['H4'] =
+ {
+ 'A4', 'H1', 'I4', 'H5', 'G6', 'H9', 'I6', 'H2', 'H6', 'C4',
+ 'H3', 'H8', 'I5', 'D4', 'G4', 'E4', 'H7', 'G5', 'F4', 'B4'
+ },
+ ['H5'] =
+ {
+ 'A5', 'H1', 'H4', 'I4', 'G6', 'H9', 'I6', 'D5', 'H2', 'H6',
+ 'E5', 'F5', 'C5', 'H3', 'H8', 'B5', 'I5', 'G4', 'H7', 'G5'
+ },
+ ['H6'] =
+ {
+ 'H1', 'H4', 'I4', 'H5', 'F6', 'H9', 'D6', 'G6', 'I6', 'H2',
+ 'E6', 'B6', 'C6', 'H3', 'H8', 'I5', 'A6', 'G4', 'H7', 'G5'
+ },
+ ['H7'] =
+ {
+ 'B7', 'H1', 'H4', 'H5', 'C7', 'I9', 'E7', 'H9', 'A7', 'H2',
+ 'H6', 'G8', 'D7', 'G7', 'G9', 'I8', 'I7', 'H3', 'H8', 'F7'
+ },
+ ['H8'] =
+ {
+ 'H1', 'E8', 'F8', 'H4', 'H5', 'I9', 'H7', 'H9', 'H2', 'H6',
+ 'G7', 'G9', 'I8', 'H3', 'I7', 'C8', 'A8', 'B8', 'G8', 'D8'
+ },
+ ['H9'] =
+ {
+ 'A9', 'H1', 'H4', 'E9', 'C9', 'H5', 'I9', 'H2', 'F9', 'H6',
+ 'B9', 'G8', 'G7', 'G9', 'I8', 'D9', 'H3', 'H8', 'I7', 'H7'
+ },
+ ['I1'] =
+ {
+ 'C1', 'H1', 'D1', 'E1', 'I3', 'I4', 'I9', 'I2', 'I6', 'F1',
+ 'H2', 'B1', 'G1', 'I8', 'I7', 'H3', 'G3', 'I5', 'A1', 'G2'
+ },
+ ['I2'] =
+ {
+ 'H1', 'I3', 'I4', 'I9', 'I6', 'F2', 'A2', 'H2', 'D2', 'G1',
+ 'E2', 'I8', 'I1', 'I7', 'H3', 'B2', 'G3', 'I5', 'C2', 'G2'
+ },
+ ['I3'] =
+ {
+ 'H1', 'I4', 'I9', 'F3', 'D3', 'I2', 'I6', 'B3', 'H2', 'G1',
+ 'E3', 'I8', 'I1', 'H3', 'I7', 'C3', 'G3', 'I5', 'A3', 'G2'
+ },
+ ['I4'] =
+ {
+ 'A4', 'H4', 'I3', 'H5', 'I9', 'I2', 'G6', 'I6', 'H6', 'C4',
+ 'I8', 'I1', 'I7', 'I5', 'D4', 'G4', 'E4', 'G5', 'F4', 'B4'
+ },
+ ['I5'] =
+ {
+ 'A5', 'H4', 'I3', 'I4', 'H5', 'I9', 'I2', 'G6', 'I6', 'D5',
+ 'H6', 'E5', 'F5', 'C5', 'I1', 'I8', 'I7', 'B5', 'G4', 'G5'
+ },
+ ['I6'] =
+ {
+ 'H4', 'I3', 'I4', 'H5', 'I9', 'I2', 'F6', 'G6', 'D6', 'E6',
+ 'H6', 'B6', 'C6', 'I1', 'I8', 'I7', 'I5', 'A6', 'G4', 'G5'
+ },
+ ['I7'] =
+ {
+ 'B7', 'I3', 'I4', 'C7', 'I9', 'E7', 'I2', 'H9', 'A7', 'I6',
+ 'G8', 'D7', 'G7', 'G9', 'I8', 'I1', 'H8', 'I5', 'F7', 'H7'
+ },
+ ['I8'] =
+ {
+ 'E8', 'F8', 'I3', 'I4', 'I9', 'I2', 'H9', 'I6', 'G8', 'G7',
+ 'G9', 'I1', 'I7', 'H8', 'I5', 'C8', 'A8', 'B8', 'H7', 'D8'
+ },
+ ['I9'] =
+ {
+ 'A9', 'E9', 'C9', 'I4', 'I3', 'I2', 'H9', 'I6', 'F9', 'B9',
+ 'G8', 'G7', 'G9', 'I8', 'I1', 'D9', 'I7', 'H8', 'I5', 'H7'
+ }
+}
+
+local grid_chars, grid_values, parse_grid, assign,
+ eliminate, solve, search, random_sudoku
+
+-- Input: a string representation
+-- Output: an association between squares and characters
+
+grid_values = function(grid)
+ local result = {}
+ local chars = string_to_table(grid)
+ assert(#chars == 81, "Invalid grid")
+
+ -- ipairs is necessary here
+
+ for k, v in ipairs(squares) do
+ result[v] = chars[k]
+ end
+ return result
+end
+
+-- Input: a table grid
+-- Output: return false if contradiction
+
+parse_grid = function(grid)
+ local values = {}
+ local gridvalues = grid_values(grid)
+
+ -- Every square can be any digit
+
+ for _, s in ipairs(squares) do
+ values[s] = digits
+ end
+
+ for s, d in pairs(gridvalues) do
+ if digits:find(d) and not assign(values, s, d) then
+ return false
+ end
+ end
+ return values
+end
+
+assign = function(values, s, d)
+ -- Eliminate all the other values and propagate
+ local result = true
+ local other_values = string_to_table(values[s]:gsub(d,''))
+ for _, d2 in ipairs(other_values) do
+ if not eliminate(values, s, d2) then
+ result = false
+ end
+ end
+ return result and values or false
+end
+
+eliminate = function(values, s, d)
+ -- Eliminate d from values[s]
+ if not values[s]:find(d) then
+ return values --Already eliminated
+ end
+ values[s] = values[s]:gsub(d,'')
+ -- 1. If a square s is reduced to one value d2, then eliminate d2 from the peers
+ if #values[s] == 0 then
+ return false
+ elseif #values[s] == 1 then
+ local check = true
+ local d2 = values[s]
+ for _, s2 in pairs(peers[s]) do
+ if not eliminate(values, s2, values[s]) then
+ check = false
+ end
+ end
+ if not check then return false end
+ end
+ -- 2. If a unit u is reduced to only one place for a value d, then put it there
+ for _, u in ipairs(units[s]) do
+ local dplaces = {}
+ for _, w in ipairs(u) do
+ if values[w]:find(d) then
+ insert(dplaces, w)
+ end
+ end
+ if #dplaces == 0 then
+ return false --contradiction
+ elseif #dplaces == 1 then
+ if not assign(values, dplaces[1], d) then
+ return false
+ end
+ end
+ end
+ return values
+end
+
+solve = function(grid)
+ return search(parse_grid(grid))
+end
+
+search = function(values)
+ local check = true
+ local n = {}
+ local s
+ if not values then
+ return false --Fail
+ end
+ for _, s in ipairs(squares) do
+ if #values[s] ~= 1 then
+ check = false
+ end
+ end
+ if check then return values end --Solved!
+ for _, x in ipairs(squares) do
+ if #values[x] > 1 then
+ insert(n, {#values[x], x})
+ end
+ end
+ sort(n, function(t1,t2) return t1[1] < t2[1] end)
+ s = n[1][2]
+ for _, d in ipairs(string_to_table(values[s])) do
+ local result = search(assign(copy(values), s, d))
+ if result then return result end
+ end
+ return false
+end
+
+-- Unused until I find a handy way to interface with ConTeXt
+
+random_sudoku = function(N)
+ local N = N or 17
+ local result = {}
+ local values = {}
+ for _, v in ipairs(squares) do
+ values[s] = digits
+ end
+ for _, v in ipairs(shuffle(squares)) do
+ if not assign(values, s, values[rows[random(9)]..columns[random(9)]]) then
+ break
+ end
+ local ds = {}
+ for _, s in ipairs(squares) do
+ if #values[s] == 1 then
+ insert(ds, values[s])
+ end
+ end
+ if #ds >= N and #unique(ds) >= 8 then
+ for _, i in ipairs(rows) do
+ for _, j in ipairs(columns) do
+ insert(result, #values[i..j]>0 and values[i..j] or "0")
+ end
+ end
+ return concat(result)
+ end
+ end
+ return random_sudoku(N)
+end
+
+-- ConTeXt functions
+
+local ctx_sudoku, ctx_solvesudoku,
+ ctx_sudokufile, ctx_solvesudokufile,
+ ctx_randomsudoku, ctx_sudokufunction,
+ ctx_typeset, ctx_error
+
+ctx_sudoku = function(grid, data)
+ local ok, result = pcall(grid_values, grid)
+ if ok then
+ ctx_typeset(result, data)
+ else
+ ctx_error("a") -- Invalid sudoku
+ end
+end
+
+ctx_sudokufile = function(file, data)
+ local ok, result = pcall(grid_values, loaddata(file))
+ if ok then
+ ctx_typeset(result, data)
+ else
+ ctx_error("b") -- "Invalid sudoku file"
+ end
+end
+
+ctx_solvesudoku = function(grid, data)
+ local ok, result = pcall(solve, grid)
+ if ok then
+ if result then
+ ctx_typeset(result, data)
+ else
+ ctx_error("c") -- "Impossible to find a solution"
+ end
+ else
+ ctx_error("a") -- "Invalid sudoku"
+ end
+end
+
+ctx_solvesudokufile = function(file, data)
+ local ok, result = pcall(solve, loaddata(file))
+ if ok then
+ if result then
+ ctx_typeset(result, data)
+ else
+ ctx_error("c") -- "Impossible to find a solution"
+ end
+ else
+ ctx_error("b") -- "Invalid sudoku file"
+ end
+end
+
+ctx_error = function(nerror)
+ local c = interfaces.constants
+ local placeholder, label, command = c.placeholder, c.label, c.command
+ c = context
+ c.sudokuparameter(placeholder .. command,
+ c.nested.sudokuparameter(placeholder .. label .. nerror)
+ )
+end
+
+local ctx_sudokufunctions =
+{
+ sudoku = ctx_sudoku,
+ sudokufile = ctx_sudokufile,
+ solvesudoku = ctx_solvesudoku,
+ solvesudokufile = ctx_solvesudokufile
+}
+
+ctx_sudokufunction = function(t)
+ ctx_sudokufunctions[t.name](t.content, t)
+end
+
+ctx_typeset = function(grid, data)
+ local alternatives =
+ {
+ {background = data.oddbackground, backgroundcolor = data.oddbackgroundcolor },
+ {background = data.evenbackground, backgroundcolor = data.evenbackgroundcolor}
+ }
+ for i, a in ipairs(rows) do
+ context.bTR()
+ for j, b in ipairs(columns) do
+ local r = grid[a..b]
+ context.bTD(alternatives[(ceil(i/3)+ceil(j/3))%2+1])
+ context(r == '0' and "" or r == '.' and "" or r)
+ context.eTD()
+ end
+ context.eTR()
+ end
+end
+
+--context.sudokuplaceholder = function(text)
+-- context.quitvmode()
+-- context.framed(context.nested.type(text))
+--end
+
+implement{
+ name = "sudokufunction",
+ arguments = {"hash"},
+ actions = ctx_sudokufunction
+}
diff --git a/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.mkvi b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.mkvi
new file mode 100644
index 0000000000..45ee942bf6
--- /dev/null
+++ b/macros/context/contrib/context-sudoku/sudoku/tex/context/third/sudoku/t-sudoku.mkvi
@@ -0,0 +1,217 @@
+%D \module
+%D [ file=t-sudoku,
+%D version=2023-05-15,
+%D title=\CONTEXT\ User Module,
+%D subtitle=Sudokus for ConTeXt,
+%D author=Jairo A. del Rio,
+%D date=\currentdate,
+%D copyright=Jairo A. del Rio,
+%D email=jairoadelrio6@gmail.com,
+%D license=MIT License]
+
+%C Copyright (c) 2021-2023 Jairo A. del Rio
+%C
+%C Permission is hereby granted, free of charge, to any person obtaining
+%C a copy of this software and associated documentation files (the
+%C "Software"), to deal in the Software without restriction, including
+%C without limitation the rights to use, copy, modify, merge, publish,
+%C distribute, sublicense, and/or sell copies of the Software, and to
+%C permit persons to whom the Software is furnished to do so, subject to
+%C the following conditions:
+%C
+%C The above copyright notice and this permission notice shall be
+%C included in all copies or substantial portions of the Software.
+%C
+%C THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+%C EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+%C MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+%C IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+%C CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+%C TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+%C SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+%D I'm not fond of sudokus. In fact, I seldom solve one or two in a row.
+%D However, they come in handy in puzzle books and existing packages are
+%D LaTeX or Python specific. Being so, a ConTeXt dedicated module is
+%D more comfortable and customizable. After all, ConTeXt is about control
+%D as Hans often says.
+
+\writestatus{loading}{Sudokus for ConTeXt}
+\writestatus{loading}{A Lua port of Peter Norvig's sudoku solver}
+
+\startmodule[sudoku]
+
+%D As always, Lua does the hard job
+
+\ctxloadluafile{t-sudoku}
+
+\unprotect
+
+%D \type{\definesudoku} is not really required
+
+\installnamespace {sudoku}
+\installsimplecommandhandler\????sudoku{sudoku}\????sudoku
+
+%D Some aliases
+
+\let\setupsudokus\setupsudoku
+
+%D Basic setups
+%D
+%D In order not to define new constants/variables, recycling existing
+%D ones looks better (trick learnt from Aditya Mahajan's modules).
+
+\setupsudokus
+ [\c!size=1.5em,
+ \c!align={\v!middle,\v!lohi},
+ \v!even\c!background=\v!color,
+ \v!odd\c!background=\v!color,
+ \v!even\c!backgroundcolor=white,
+ \v!odd\c!backgroundcolor=gray,
+ \c!placeholder\c!label a=Invalid sudoku,
+ \c!placeholder\c!label b=Invalid sudoku file,
+ \c!placeholder\c!label c=Impossible to find a solution,
+ \c!placeholder\c!command=\framed]
+
+%D A generic sudoku generator macro
+%D Yeah, I'm that lazy
+
+\unexpanded\def\sudokufunction_name{\dodoubleempty\sudokufunction_direct}
+
+%D Passing values to TABLE's is easier and unknown keys will be ignored.
+%D However, we need to enforce a square shape.Hence the need to passing
+%D values twice.
+
+\def\sudokufunction_direct[#name][#parameters]#content%
+ {\begingroup%
+ \ifsecondargument
+ \setupTABLE[#parameters]%
+ \setupsudokus[#parameters]%
+ \fi
+ \bTABLE
+ [\c!align=\sudokuparameter\c!align,
+ \c!width=\sudokuparameter\c!size,
+ \c!height=\sudokuparameter\c!size]
+ \clf_sudokufunction
+ [name =#name,
+ content ={#content},
+ evenbackground =\sudokuparameter{\v!even\c!background},
+ oddbackground =\sudokuparameter{\v!odd\c!background},
+ evenbackgroundcolor =\sudokuparameter{\v!even\c!backgroundcolor},
+ oddbackgroundcolor =\sudokuparameter{\v!odd\c!backgroundcolor}]
+ \eTABLE%
+ \endgroup}
+
+%D Sudoku macros
+
+\def\sudoku{\sudokufunction_name[sudoku]}
+\def\sudokufile{\sudokufunction_name[sudokufile]}
+\def\solvesudoku{\sudokufunction_name[solvesudoku]}
+\def\solvesudokufile{\sudokufunction_name[solvesudokufile]}
+
+%D More aliases
+
+\let\solvedsudoku\solvesudoku
+\let\solvedsudokufile\solvesudokufile
+
+\protect
+
+\stopmodule
+
+\continueifinputfile{t-sudoku.mkvi}
+
+%D Some examples
+
+\usecolors[svg]
+\setupsudokus[oddbackgroundcolor=paleturquoise,evenbackgroundcolor=aliceblue]
+
+\starttext
+
+\startsection[title={\type{\sudoku}}]
+
+\sudoku{
+......... ........1 .....2.3.
+....1...4 ..3.5.... .26....7.
+14...8... 5........ 7....6.2.
+}
+
+\blank[line]
+
+\sudoku{
+000000001 000002030 004056000
+000004500 010700000 080000400
+000030000 000100008 205000000
+}
+
+\blank[line]
+
+\sudoku
+{
+000000000 111111111 222222222
+333333333 444444444 555555555
+666666666 777777777 888888888
+}
+
+\blank[line]
+
+\sudoku{666}
+
+\stopsection
+
+\startsection[title={\type{\solvesudoku}}]
+
+\solvesudoku[size=9mm,evenbackgroundcolor=gray,oddbackgroundcolor=white]{
+.......... .......1 .....2.3.
+....1...4. .3.5.... .26....7.
+14...8...5 ........ 7....6.2.
+}
+
+\blank[line]
+
+\solvedsudoku{
+000000001 000002030 004056000
+000004500 010700000 080000400
+000030000 000100008 205000000
+}
+
+\blank[line]
+
+\solvesudoku
+{
+000000000 111111111 222222222
+333333333 444444444 555555555
+666666666 777777777 888888888
+}
+
+\stopsection
+
+\startsection[title={\type{\sudokufile}}]
+
+\sudokufile[evenbackgroundcolor=cornsilk,oddbackgroundcolor=pink]{t-sudoku-test-01.txt}
+
+\blank[line]
+
+\sudokufile{t-sudoku-test-03.txt}
+
+\blank[line]
+
+\sudokufile[rulethickness=2pt,evenbackgroundcolor=cornsilk]{t-sudoku-test-02.txt}
+
+\stopsection
+
+\startsection[title={\type{\solvesudokufile}}]
+
+\setupsudokus[oddbackgroundcolor=plum,evenbackgroundcolor=pink]%
+\solvesudokufile[oddbackgroundcolor=thistle]{t-sudoku-test-01.txt}
+
+\blank[line]
+
+\solvesudokufile{t-sudoku-test-02.txt}
+
+\blank[line]
+
+\solvesudokufile{t-sudoku-test-03.txt}
+
+\stopsection
+
+\stoptext