sourcegames/sudoku/SudokuGrid.xtl
1⍝# Sudoku's rules and a solver, a library: sudoku.xtl (scripted),
2⍝# play.xtl (at the terminal) and the web page all use these. (Named
3⍝# SudokuGrid because a disk that ignores case cannot hold both
4⍝# Sudoku.xtl and sudoku.xtl.) A grid is a vector of 81 digits, row by
5⍝# row, 0 an empty cell. A game's state is the puzzle's givens (81),
6⍝# then the grid as filled so far (81).
7
8j ← (r̲ange 9) − 1
9cell ← (r̲ange 81) − 1
10
11⍝ :: Unit -> Int
12⍝# The 27 units (9 rows, 9 columns, 9 boxes) as a 27 by 9 table of the
13⍝# cells (from 1) in each.
14ˡu̲nits ← { @ → 1 + ((9 × j) '+ t̲able j) c̲at (j '+ t̲able 9 × j) c̲at ((27 × j d̲iv 3) + 3 × j m̲od 3) '+ t̲able (9 × j d̲iv 3) + j m̲od 3 }
15⍝ :: Unit -> Int
16⍝# The other way round: each cell's three units (from 1), its row's,
17⍝# its column's and its box's, as a 3 by 81 table.
18ˡh̲omes ← { @ → 3 81 r̲eshape 1 + (cell d̲iv 9) c̲at (9 + cell m̲od 9) c̲at 18 + (3 × cell d̲iv 27) + (cell m̲od 9) d̲iv 3 }
19
20⍝ :: (Num a, Truthy a) => Int -> a
21⍝# The digits placed, one-hot: 81 by 9, a 1 at each filled cell's digit.
22ˡo̲nehot ← { g → 0 + g '= t̲able r̲ange 9 }
23⍝ :: Num a => a -> a
24⍝# How many times each digit appears in each unit, all 27 at once: the
25⍝# unit table selects its cells' rows of m (27 by 9 by 9), summed over
26⍝# the 9 cells.
27ˡp̲erUnit ← { m → '+ r̲/₂ (ˡu̲nits @) s̲elect m }
28⍝ :: Num a => a -> a
29⍝# Back to the cells: each cell's sum of its three units' rows of t
30⍝# (27 by 9 in, 81 by 9 out).
31ˡp̲erCell ← { t →
32 h ← ˡh̲omes @
33 ((1 s̲elect h) s̲elect t) + ((2 s̲elect h) s̲elect t) + (3 s̲elect h) s̲elect t
34}
35⍝ :: (Num a, Truthy a) => Int -> a
36⍝# The candidates, 81 by 9: a digit is open in an empty cell when none
37⍝# of the cell's units holds it yet; a filled cell keeps its digit.
38ˡc̲andidates ← { g →
39 f ← ˡo̲nehot g
40 open ← (g = 0) '× t̲able 9 r̲eshape 1
41 0 + (0 < f) ∨ (0 < open) ∧ 0 = ˡp̲erCell ˡp̲erUnit f
42}
43⍝ :: (Num a, Num b, Num c, Truthy c) => a -> b -> c
44⍝# The singles of grid g with candidates c, one-hot (81 by 9): a naked
45⍝# single is an empty cell with one candidate left; a hidden single a
46⍝# digit with only one place left in one of the cell's units.
47ˡs̲ingles ← { g c →
48 empty ← 0 < (g = 0) '× t̲able 9 r̲eshape 1
49 naked ← (0 < c) ∧ (1 = '+ r̲/₂ c) '× t̲able 9 r̲eshape 1
50 hidden ← (0 < c) ∧ 0 < ˡp̲erCell 0 + 1 = ˡp̲erUnit c
51 0 + empty ∧ naked ∨ hidden
52}
53⍝ :: Int -> Int
54⍝# One round: every single filled at once. A cell given two digits at
55⍝# once means the grid has no solution: -1 in every cell.
56ˡr̲ound ← { g →
57 s ← g ˡs̲ingles ˡc̲andidates g
58 1 < 'm̲ax r̲/ '+ r̲/₂ s ? 81 r̲eshape -1
59 g + '+ r̲/₂ s × 81 9 r̲eshape r̲ange 9
60}
61⍝ :: Int -> Int
62⍝# Rounds until nothing changes (or a contradiction).
63ˡp̲ropagate ← { g →
64 h ← ˡr̲ound g
65 h m̲atch g ? g
66 0 > 'm̲in r̲/ h ? h
67 ˡp̲ropagate h
68}
69⍝ :: (Num a, Num b, Truthy b) => Int -> a -> b
70⍝# 1 when grid g (candidates c) cannot be completed: a contradiction
71⍝# marked, a digit twice in a unit, or an empty cell with no candidate.
72ˡb̲roken ← { g c →
73 0 > 'm̲in r̲/ g ? 1
74 1 < 'm̲ax r̲/ r̲avel ˡp̲erUnit ˡo̲nehot g ? 1
75 0 < '+ r̲/ 0 + (g = 0) ∧ 0 = '+ r̲/₂ c
76}
77⍝ :: Int -> Int
78⍝# The solution of grid g (-1 in every cell when there is none):
79⍝# propagation, then a guess in the cell with the fewest candidates,
80⍝# each candidate in turn, each guess propagated again.
81ˡs̲olve ← { g →
82 h ← ˡp̲ropagate g
83 c ← ˡc̲andidates h
84 h ˡb̲roken c ? 81 r̲eshape -1
85 0 = '+ r̲/ 0 + h = 0 ? h
86 k ← f̲irst g̲rade ('+ r̲/₂ c) + 10 × h ≠ 0
87 h ˡt̲ry k c̲at w̲here k s̲elect c
88}
89⍝ :: Int -> Int -> Int
90⍝# Guessing: kd is the cell and the digits still to try there.
91ˡt̲ry ← { g kd →
92 2 > t̲ally kd ? 81 r̲eshape -1
93 r ← ˡs̲olve g + (2 s̲elect kd) × (f̲irst kd) = r̲ange 81
94 0 > 'm̲in r̲/ r ? g ˡt̲ry (f̲irst kd) c̲at 2 d̲rop kd◆ r
95}
96⍝ :: Num a => Int -> a
97⍝# How many rounds propagation takes on grid g.
98ˡr̲ounds ← { g →
99 h ← ˡr̲ound g
100 (h m̲atch g) ∨ 0 > 'm̲in r̲/ h ? 0
101 1 + ˡr̲ounds h
102}
103
104⍝## The game
105
106⍝# The puzzles: Wikipedia's example; one with 17 givens, the fewest a
107⍝# sudoku with one solution can have; two that singles alone cannot
108⍝# finish (Peter Norvig's first hard one, and Arto Inkala's, called the
109⍝# hardest in 2012).
110wikipedia ← 5 3 0 0 7 0 0 0 0 6 0 0 1 9 5 0 0 0 0 9 8 0 0 0 0 6 0 8 0 0 0 6 0 0 0 3 4 0 0 8 0 3 0 0 1 7 0 0 0 2 0 0 0 6 0 6 0 0 0 0 2 8 0 0 0 0 4 1 9 0 0 5 0 0 0 0 8 0 0 7 9
111seventeen ← 0 0 0 0 0 0 0 1 0 4 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 5 0 4 0 7 0 0 8 0 0 0 3 0 0 0 0 1 0 9 0 0 0 0 3 0 0 4 0 0 2 0 0 0 5 0 1 0 0 0 0 0 0 0 0 8 0 6 0 0 0
112norvig ← 4 0 0 0 0 0 8 0 5 0 3 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 2 0 0 0 0 0 6 0 0 0 0 0 8 0 4 0 0 0 0 0 0 1 0 0 0 0 0 0 0 6 0 3 0 7 0 5 0 0 2 0 0 0 0 0 1 0 4 0 0 0 0 0 0
113inkala ← 8 0 0 0 0 0 0 0 0 0 0 3 6 0 0 0 0 0 0 7 0 0 9 0 2 0 0 0 5 0 0 0 7 0 0 0 0 0 0 0 4 5 7 0 0 0 0 0 1 0 0 0 3 0 0 0 1 0 0 0 0 6 8 0 0 8 5 0 0 0 1 0 0 9 0 0 0 0 4 0 0
114⍝ :: Unit -> Int
115⍝# The puzzles, easiest first, one per row (81 digits).
116ˡp̲uzzles ← { @ → 4 81 r̲eshape wikipedia c̲at seventeen c̲at norvig c̲at inkala }
117⍝ :: Int -> Int
118⍝# A new game on puzzle n (1 to 4): the givens, and the grid so far.
119ˡn̲ew ← { n →
120 g ← n s̲elect ˡp̲uzzles @
121 g c̲at g
122}
123⍝ :: a -> a
124⍝# The puzzle's givens (81 digits, 0 an empty cell).
125ˡg̲ivens ← { s → 81 t̲ake s }
126⍝ :: a -> a
127⍝# The grid as filled so far (81 digits).
128ˡg̲rid ← { s → 81 d̲rop s }
129⍝ :: Num a => Int -> Int -> a
130⍝# Why digit d cannot go at row r, column c (rcd is r c d; d 0 clears
131⍝# the cell): 0 it can, 1 off the board, 2 a given, 3 a peer holds d.
132ˡw̲hy ← { s rcd →
133 (0 < 'm̲in r̲/ 2 t̲ake rcd) ∧ (9 ≥ 'm̲ax r̲/ 2 t̲ake rcd) ∧ (0 ≤ 3 s̲elect rcd) ∧ 9 ≥ 3 s̲elect rcd ? s ˡc̲lash rcd◆ 1
134}
135⍝ :: Num a => Int -> Int -> a
136⍝# Why digit d cannot go at row r, column c, given that rcd is on the board: 0 it can, 2 a given, 3 a peer holds d.
137ˡc̲lash ← { s rcd →
138 k ← 1 + (9 × (f̲irst rcd) − 1) + (2 s̲elect rcd) − 1
139 0 < k s̲elect ˡg̲ivens s ? 2
140 d ← 3 s̲elect rcd
141 g ← (ˡg̲rid s) × k ≠ r̲ange 81
142 (d = 0) ∨ d m̲ember? w̲here k s̲elect ˡc̲andidates g ? 0◆ 3
143}
144⍝ :: Int -> Int -> Int
145⍝# Digit d at row r, column c (d 0 clears it), when it may go there.
146ˡm̲ove ← { s rcd →
147 0 < s ˡw̲hy rcd ? s
148 k ← 1 + (9 × (f̲irst rcd) − 1) + (2 s̲elect rcd) − 1
149 (ˡg̲ivens s) c̲at ((ˡg̲rid s) × k ≠ r̲ange 81) + (3 s̲elect rcd) × k = r̲ange 81
150}
151⍝ :: (Num a, Truthy a) => Int -> a
152⍝# The candidates of the grid so far, 81 by 9.
153ˡl̲egal ← { s → ˡc̲andidates ˡg̲rid s }
154⍝ :: (Num a, Truthy a) => Int -> a
155⍝# 1 solved, else 0 (playing).
156ˡs̲tatus ← { s → 0 + (0 = '+ r̲/ 0 + 0 = ˡg̲rid s) ∧ n̲ot (ˡg̲rid s) ˡb̲roken ˡl̲egal s }
157⍝ :: Int -> Int
158⍝# A hint, as row, column and digit: the first single of the grid so
159⍝# far, else the first empty cell's digit in the solution; 0 0 0 when
160⍝# the grid so far has no solution (a digit placed wrong).
161ˡh̲int ← { s →
162 g ← ˡg̲rid s
163 x ← ˡs̲olve g
164 0 > 'm̲in r̲/ x ? 0 0 0
165 one ← w̲here 0 < '+ r̲/₂ g ˡs̲ingles ˡc̲andidates g
166 k ← f̲irst one c̲at w̲here g = 0
167 (1 + (k − 1) d̲iv 9) c̲at (1 + (k − 1) m̲od 9) c̲at k s̲elect x
168}
169⍝ :: Int -> Char
170⍝# A grid as text: digits, . for an empty cell, the boxes ruled off.
171ˡs̲hown ← { g →
172 m ← (9 9 r̲eshape (1 + g) s̲elect ".123456789") c̲at₂ 9 2 r̲eshape " |"
173 r ← 1 10 2 10 3 10 11 10 4 10 5 10 6 10 11 10 7 10 8 10 9 s̲elect₂ m
174 1 2 3 10 4 5 6 10 7 8 9 s̲elect r c̲at 1 21 r̲eshape "------+-------+------"
175}
176⍝ :: Int -> Char
177⍝# The game's grid so far.
178ˡv̲iew ← { s → ˡs̲hown ˡg̲rid s }