#!apl --script ⍝ ⍝ Author: Jürgen Sauermann ⍝ Date: 24.12.2016 ⍝ Copyright: Copyright (C) 2016 by Jürgen Sauermann ⍝ License: GPL see http://www.gnu.org/licenses/gpl-3.0.en.html ⍝ email: bug-apl@gnu.org ⍝ Portability: L3 (GNU APL) ⍝ ⍝ Purpose: ⍝ This workspace solves sudokus by using ⎕DLX (aka. Knuth's Dancing Links) and ⍝ the contraints matrix described at: ⍝ http://www.stolaf.edu/people/hansonr/sudoku/exactcovermatrix.htm ⍝ ⍝ Description: ⍝ ⍝ )LOAD ./sudoku_DLX.apl ⍝ ⍝ -or- ⍝ ⍝ apl -f ./sudoku_DLX.apl ⍝ ⍝ You can override the sudokus below with the one that you would like to solve ⍝ ⎕PW←400 ⍝ for displaying many constraints columns SUDO_p5 ← ⊃⎕INP '▄' ⍝ page 4 ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ 2 │ │ ║ │ │ 5 ║ │ │ 7 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 4 │ ║ 6 │ │ 8 ║ │ 9 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ 1 │ │ 9 ║ │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ 8 │ 3 ║ │ │ ║ 7 │ 4 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 1 │ 7 │ 9 ║ │ │ ║ 6 │ 5 │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ │ ║ 9 │ │ 4 ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 5 │ ║ 8 │ │ 3 ║ │ 1 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 4 │ │ ║ │ │ ║ │ │ 8 ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ SUDO_sdk_10 ← ⊃⎕INP '▄' ⍝ page 10 ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ │ 9 │ ║ │ │ 8 ║ 1 │ 6 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ 1 ║ 7 │ │ ║ 9 │ 2 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 2 │ │ ║ │ │ ║ │ │ 3 ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ 3 │ │ 8 ║ 4 │ │ 1 ║ 5 │ │ 6 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 4 │ 9 ║ 8 │ │ ║ 2 │ 3 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 6 │ │ ║ │ │ 7 ║ 8 │ │ 4 ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ 8 │ │ ║ 6 │ 4 │ ║ │ │ 9 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ 7 │ 2 ║ 6 │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 6 │ 7 ║ 1 │ 8 │ ║ │ 5 │ 2 ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ SUDO_sdk_16 ← ⊃⎕INP '▄' ⍝ page 12 ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ 2 │ │ 7 ║ │ 4 │ ║ 6 │ │ 8 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 4 │ 3 │ 5 ║ 9 │ 6 │ 8 ║ 7 │ 1 │ 2 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 6 │ 8 ║ 7 │ │ ║ │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ 5 │ 4 │ 1 ║ 6 │ 3 │ 9 ║ 2 │ 8 │ 7 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 6 │ 7 │ 2 ║ │ 8 │ ║ │ │ 3 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 3 │ 8 │ 9 ║ 2 │ 7 │ 5 ║ 4 │ 6 │ 1 ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ │ ║ │ │ 6 ║ │ 7 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 8 │ 5 │ 6 ║ 3 │ │ 7 ║ 1 │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 7 │ │ ║ │ 1 │ ║ │ │ 6 ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ SUDO_sdk_23 ← ⊃⎕INP '▄' ⍝ page 26 ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ 5 │ │ 2 ║ │ │ ║ 4 │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ 7 │ 1 │ ║ │ │ 3 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ │ ║ │ │ 4 ║ 6 │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 7 │ ║ 2 │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 1 │ ║ │ │ ║ │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ 6 │ │ ║ │ │ 2 ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ 3 │ ║ │ 1 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 4 │ │ ║ │ │ ║ │ │ ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ SUDO_5←⊃⎕INP '▄' ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ │ │ 9 ║ 5 │ │ 6 ║ 1 │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 6 │ 7 ║ │ 1 │ ║ │ 9 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 1 │ │ 8 ║ │ │ ║ 5 │ 4 │ 6 ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ 7 │ │ ║ 4 │ │ 2 ║ │ │ 5 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 5 │ ║ │ 8 │ ║ │ 7 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ 4 │ │ ║ 7 │ │ 9 ║ │ │ 8 ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ 2 │ 3 │ 4 ║ │ │ ║ 8 │ │ 1 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 9 │ ║ │ 3 │ ║ 7 │ 2 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ 1 ║ 2 │ │ 8 ║ 3 │ │ ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ SUDO_Xtian←⊃⎕INP '▄' ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ 4 │ │ 5 ║ │ │ 2 ║ │ 7 │ 1 ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ 9 ║ │ 4 │ ║ │ │ 6 ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ │ ║ 9 │ │ ║ 8 │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 3 │ ║ │ │ 6 ║ │ 4 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ 3 │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ 1 │ ║ │ 6 │ ║ │ 8 │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ 7 │ ║ │ 2 │ 1 ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ 8 ║ │ │ ║ │ │ ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ SUDO_EMPTY←⊃⎕INP '▄' ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ║ │ │ ║ │ │ ║ │ │ ║ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝▄ ∇Z←DECORATE SUDO;ROWS;COLS ⍝ ⍝ A raw sudoko is a 9×9 numeric matrix with values 0 (for empty fields) and ⍝ 1-9 for placed digits. ⍝ ⍝ A decorated sudoku is a 19×37 character matrix which also contains line ⍝ graphic characters between the 9×9 fields (like the sudokus shown above). ⍝ ⍝ This function converts a raw sudoko into a decorated sudoku, and vice versa. ⍝ DX←37⍴0 0 1 0 ◊ DY←19⍴0 1 ⍝ the relevant columns and rows →(9 9≡⍴SUDO)⍴RAW_TO_DECORATED ◊ Z←' 123456789'⍳DY⌿DX/SUDO ◊ →0 RAW_TO_DECORATED: Z←SUDO_EMPTY ◊ (DY⌿DX/Z)←⎕UCS 48+SUDO-16×SUDO=0 ∇ ∇Z←SETUP_CONSTRAINTS;ROW;COL;DIG;DC;I ⍝ ⍝ Return the constraints matrix of the empty sudoku. This matrix uses ⍝ characters 1-9 and spaces instead of the "normal" integers 0 and 1 for ⍝ a constraints matrix. ⍝ I←0 ◊ Z←729 324⍴' ' LOOP: (ROW COL DIG)←9 9 9⊤I ◊ DC←⎕UCS 49+DIG Z[I;(9⊥ROW COL),(81+9⊥ROW DIG),(162+9⊥COL DIG),243+9⊥(3⊥2⍴3 3⊤ROW COL),DIG]←DC →(729>I←I+1)⍴LOOP ∇ ∇A SHOW SOLUTION;SUDO_OUT;Q ⍝ ⍝ Display the input sudoku A and its (decorated) solution ⍝ SUDO_OUT←A ⊣{SUDO_OUT[R;C]←D+1 ⊣ (R C D)←9 9 9⊤⍵;R;C;D}¨⊃⍬⍴SOLUTION ⍝ apply moves (DECORATE A) (DECORATE SUDO_OUT) →0 ⍝ check result ⍝ { Q[⍋Q←,SUDO_OUT[⍵;]] ≡ 1+⍳9 } ¨ ⍳9 { Q[⍋Q←,SUDO_OUT[;⍵]] ≡ 1+⍳9 } ¨ ⍳9 { Q[⍋Q←,SUDO_OUT[0 1 2 + ⍵[1];0 1 2 + ⍵[0]]] ≡ 1+⍳9 } ¨ ,3×⍳3 3 ∇ ∇SOLVE SUDO;⎕IO;RAW;CONSTRAINTS;WL;SOLUTIONS ⍝ ⍝ solve (decorated) sudoku SUDO ⍝ ⍝ Step 1: setup the constraints matrix for an empty sudoku ⍝ ⎕IO←0 ⍝ this simplifies ⊥ and ⊤ CONSTRAINTS←SETUP_CONSTRAINTS ◊ RAW←DECORATE SUDO ⍝ Step 2: create a worklist WL of RCDs that shall be placed ⍝ WL←9⊥⍉(WL≥0)⌿(9/⍳9), (81⍴⍳9), 81 1⍴+WL←,RAW-1 ⍝ map digits 1-9 to 0-8 'Number of digits pre-placed: ' (⍬⍴⍴WL) ⍝ Step 3: place every RCD in WL onto the sudoku. Placing an RCD causes some ⍝ rows of the constraints matrix to be cleared and some columns to be ⍝ removed from the matrix. ⍝ CONSTRAINTS← (¯4, WL) ⎕DLX CONSTRAINTS≠' ' ⍝ Step 4: solve remaining constraints matrix CONSTRAINTS using ⎕DLX ⍝ 'Size of the constraints matrix:' (⍴CONSTRAINTS) 'Number of non-empty rows: ' (729-+/0=+/CONSTRAINTS) SOLUTIONS←¯1 ⎕DLX CONSTRAINTS 'Number of solutions: ' (⍬⍴⍴SOLUTIONS) ⍝ Step 5: display the solution(s) (if any) ⍝ →(0=⍴SOLUTIONS)⍴0 '' ◊ ' first solution:' ◊ RAW SHOW 1↑SOLUTIONS ◊ →(1=⍴SOLUTIONS)⍴0 '' ◊ ' last solution:' ◊ RAW SHOW ¯1↑SOLUTIONS ∇ SOLVE SUDO_p5 SOLVE SUDO_sdk_10 SOLVE SUDO_sdk_16 SOLVE SUDO_sdk_23 SOLVE SUDO_5 SOLVE SUDO_Xtian )OFF ⍝ ⍝ EOF