I have programmed many things in many programming languages, and Prolog is not one of those languages. I am supposed to write a program that will solve a sudoku puzzle when given a puzzle representation as input.
My idea:
Store all supplied numbers in a list of lists (list of rows), and brute force the possible options until one fits (I know, it's not the most elegant, but I don't have a lot of time to spend writing out the logic to solve the puzzle conventionally). But, being new to Prolog, I am having some difficulty understanding the way of going about things. The input is given in a text file in the form of rows looking like
1-2---34-
-34--1-5-
and so on and so forth. My code to read and print the file is:
readPuzzle(File) :-
see(File),
repeat,
get_char(X),
(X = end_of_file, !
;
write(X),
fail
),
seen.
This works all well and good. So let's say I try to build this list by adding a W = []
just above see(File)
and replace write(X)
with W = [W|X]
. From my experience, this should create a long list of all of the chars supplied from the text file.
It doesn't.
Someone please either
There are several ways of accomplish the specification reading. If you are willing to reuse your code, I would suggest to use assertz:
:- dynamic onechar/1.
readPuzzle(File) :-
see(File),
repeat,
get_char(X),
(X = end_of_file, !
;
asssertz(onechar(X)), % write(X),
fail
),
seen.
and use
..., findall(L, retract(onechar(C)), Cs), ...
to get the list of chars read, then you will need to split the list in lines, discarding lines' separators.
Otherwise, instead of asserting/retracting, we can use service predicate that collects more structured input, and constraints length while reading:
readPuzzle(File, Puzzle) :-
see(File),
length(Puzzle, 9), % this allocates a list of unbound variables
maplist(read_a_line, Puzzle),
seen.
read_a_line(Line) :-
length(Line, 9),
maplist(get_char, Line),
get_char(_). % get rid of nl
For an example of how this works in SWI-Prolog:
?- length(L,9),see(user),maplist(get,L),seen.
|: 987654321
L = [57, 56, 55, 54, 53, 52, 51, 50, 49].
update
Here is another way, using accumulators to collect structured input and size..
readPuzzle(File, Puzzle, Length) :-
see(File),
readLines([], 0, Puzzle, Length),
seen.
readLines(SoFar, CountSoFar, Lines, CountLines) :-
get_char(C), % lookahead
C \= end_of_file,
readLine(C, [], Line),
M is SoFar + 1,
readLines([Line|SoFar], M, Lines, CountLines).
readLines(Lines, TotLines, Lines, TotLines).
readLine(C, Line, Line) :-
C == 10.
readLine(C, SoFar, Line) :-
get_char(S),
readLine(S, [C|SoFar], Line).