1) The array bits contains the sequence of values (i,2^i) for i from 0 to 9.
let bits = init 9 (fun b -> b, 1 lsl b)
2) The array group contains for each cell the indices of the three groups of constraints containing that cell.
let group = init 81 (fun i -> [| i/9; 9 + i mod 9; 18 + (i/27)*3 + (i mod 9) / 3 |])
3) The card array stores for each integer the number of bits set to 1 in its binary representation.
let card = init 512 (fun i -> fold_left (fun a (b,s) -> if i land s > 0 then a+1 else a) 0 bits)
4) The recursive solve function is the backtrack function
let rec solve grid =
5) The array free contains for each group of constraints a field of bit (an int)
the k-ith bit is set if and only if the value (k+1) is not yet used in the group.
let free = make 27 511 in
6) For each cell, for each group containing that cell, we unset the bit corresponding to the value of the cell.
iteri (fun i v -> iter (fun g -> free.(g) <- free.(g) - (1 lsl (v-1))) group.(i)) grid;
7) For each cell, the possibilities left are the intersection of the values unused
in the three groups of contraints containing the cell
let poss = mapi (fun i v -> (i,v), fold_left (fun a g -> a land free.(g)) 511 group.(i)) grid in
8) We extract the index of the cell c which has not yet a value and which minimises the number of possibilities.
let m,c = fold_left (fun (m,c) ((i,v),p) -> if v = 0 && card.(p) < m then card.(p),i else m,c) (10,-1) poss in
9) In case all cells have a value, we have a solution, we print it.
if m = 10 then (iteri (fun i v -> print_int v; if i mod 9 = 8 then print_char '\n') grid; print_char '\n')
10) In case m = 0, at least one cell has no possibility left, there is no solution, we simply return.
Otherwise, m > 0, we try recursively all legal values for the cell c selected previously.
else if m > 0 then iter (fun (b,s) -> if (snd poss.(c)) land s > 0 then (subsolve (b+1))) bits
11) The subsolve value copy the grid, place a value, and call recursively the function solve
let subsolve value = let grid2 = copy grid in grid2.(c) <- value; solve grid2 in
12) To read one character and obtain the corresponding digit:
let inp() = int_of_char (input_char stdin) - 48 in
13) To call function solve on the input grid:
solve (init 81 (fun i -> (if i > 0 && i mod 9 = 0 then ignore (inp())); inp()))