I’m using: SWI-Prolog version 9.0.4 on Windows 11 64-bit
Rank newbie here, so please be patient!
Having read the Prolog chapter in Seven Languages In Seven Weeks, I’m trying to write a sudoku solver without looking at his code. Like him, I’m starting with a 4x4 puzzle to keep things simple.
To force myself to learn the language better, I decided not to use any built-in Prolog helpers (like fd_all_different
and fd_domain
that he uses). Instead, I decided to write in_range(List)
that checks all these elements in the list are between 1 and 4, and unique(List)
that checks that all the elements in List are different. To support that, I also wrote not_in(E, List)
that checks that the given element E does not appear in the list List.
My code for these is as follows…
in_range([]).
in_range([H|T]) :- H > 0, H < 5, in_range(T).
not_in(_, []).
not_in(E, [E]) :- false.
not_in(E, [H|T]) :- E =\= H, not_in(E, T).
unique([]).
unique([H|T]) :- not_in(H, T), unique(T).
I tried these out on a few sample lists, and they seem to wrk fine.
I then tried to use them together to solve a puzzle…
sudoku([A1,A2,A3,A4,B1,B2,B3,B4,C1,C2,C3,C4,D1,D2,D3,D4]) :-
% all numbers have to be between 1 and 4
in_range([A1,A2,A3,A4,B1,B2,B3,B4,C1,C2,C3,C4,D1,D2,D3,D4]),
unique([A1,A2,A3,A4]), % row A
unique([B1,B2,B3,B4]), % row B
unique([C1,C2,C3,C4]), % row C
unique([D1,D2,D3,D4]), % row D
unique([A1,B1,C1,D1]), % col 1
unique([A2,B2,C2,D2]), % col 2
unique([A3,B3,C3,D3]), % col 3
unique([A4,B4,C4,D4]), % col 4
unique([A1,A2,B1,B2]), % tl square
unique([A3,A4,B3,B4]), % tr square
unique([C1,C2,D1,D2]), % bl square
unique([C3,C4,D3,D4]), % br square
!. % take 1st result
However, this gave an error “Arguments are not sufficiently instantiated.”
I’ve spent quite a bit of time searching, but can’t underatand what I’m doing wrong.
As I said, I’m a rank newbie at prolog, so if anyone can explain what I’m doing wrong I’d be very grateful.
Thanks