有几种方法可以完成规范阅读。如果您愿意重用您的代码,我建议使用 assertz:
:- dynamic onechar/1.
readPuzzle(File) :-
see(File),
repeat,
get_char(X),
(X = end_of_file, !
;
asssertz(onechar(X)), % write(X),
fail
),
seen.
并使用
..., findall(L, retract(onechar(C)), Cs), ...
要读取字符列表,则需要将列表拆分为行,丢弃行的分隔符。
否则,我们可以使用服务谓词来收集更多结构化输入和约束长度,而不是断言/撤回:
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
有关如何在 SWI-Prolog 中工作的示例:
?- length(L,9),see(user),maplist(get,L),seen.
|: 987654321
L = [57, 56, 55, 54, 53, 52, 51, 50, 49].
更新
这是另一种方式,使用累加器来收集结构化输入和大小。
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).