try_values([], []) -> error("No solution found");
try_values([Solution], []) -> Solution;
try_values(_, []) -> error("Bad sudoku: multiple solutions");
try_values(Heads, [0|Tail]) ->
NewHeads = case Heads of
[] -> [[P] || P <- pos()];
_ -> [Head++[P] || P <- pos(), Head <- Heads]
end,
ValidHeads = [Head || Head <- NewHeads, valid(Head++Tail)],
try_values(ValidHeads, Tail);
try_values([], [H|Tail]) -> try_values([[H]], Tail);
try_values(Heads, [H|Tail]) -> try_values([Head++[H] || Head <- Heads], Tail).
solve(Board) ->
case valid(Board) of
true -> try_values([], Board);
false -> error("No solution found")
end.
try_values
does what you described. It builds solution by going through Board
, trying all possible solutions (from pos()
) when it finds 0
and collecting valid
solutions in ValidHeads
to pass them further to continue. Thus, it goes all possible ways, if at some point there are multiple valid
sudoku they all will be added to Heads
and will be tested on valid
ity on following steps. solve
is just a wrapper to call try_values([], Board)
.
Basically, the way to iterate recursively over 0's
is to skip all non-zeros (2 last try_values
expression) and do the job on zeros (fourth try_values
expression).
First three try_values
expressions check if solution is exist and single and return it in that case.