编辑:请参阅下面的答案,了解我为什么是个傻瓜。在这方面仍有一个谜,我很乐意回答。
我长期坚持这一点。我正试图在漂亮的网格中打印出一个数独的解决方案。
我认为我遇到了问题,因为我不了解Prolog中模式匹配的一些关键部分。
不用多说,我的代码:
prettier_print([]).
prettier_print([Puzzle]) :- prettier_print(0, [Puzzle]).
prettier_print(0, Puzzle) :-
writeln('┌───────┬───────┬───────┐'),
prettier_print(1, Puzzle).
prettier_print(4, Puzzle) :-
writeln('│───────┼───────┼───────│'),
prettier_print(5, Puzzle).
prettier_print(8, Puzzle) :-
writeln('│───────┼───────┼───────│'),
prettier_print(9, Puzzle).
prettier_print(12, []) :-
writeln('└───────┴───────┴───────┘').
prettier_print(N, [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9 | Puzzle]) :-
member(N, [1,2,3,5,6,7,9,10,11]), % tried this when the line below did not work
% N =\= 0, N =\= 4, N =\= 8, N =\= 13,
format('│ ~d ~d ~d │ ~d ~d ~d │ ~d ~d ~d │~n', [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9]),
succ(N, N1),
prettier_print(N1, Puzzle).
这是电话:
prettier_print(0, [1,2,3,4,5,6,7,8,9,
2,2,3,4,5,6,7,8,9,
3,2,3,4,5,6,7,8,9,
4,2,3,4,5,6,7,8,9,
5,2,3,4,5,6,7,8,9,
6,2,3,4,5,6,7,8,9,
7,2,3,4,5,6,7,8,9,
8,2,3,4,5,6,7,8,9,
9,2,3,4,5,6,7,8,9]).
这是输出:
┌───────┬───────┬───────┐
│ 1 2 3 │ 4 5 6 │ 7 8 9 │
│ 2 2 3 │ 4 5 6 │ 7 8 9 │
│ 3 2 3 │ 4 5 6 │ 7 8 9 │
│───────┼───────┼───────│
│ 4 2 3 │ 4 5 6 │ 7 8 9 │
│ 5 2 3 │ 4 5 6 │ 7 8 9 │
│ 6 2 3 │ 4 5 6 │ 7 8 9 │
│───────┼───────┼───────│
│ 7 2 3 │ 4 5 6 │ 7 8 9 │
│ 8 2 3 │ 4 5 6 │ 7 8 9 │
│ 9 2 3 │ 4 5 6 │ 7 8 9 │
└───────┴───────┴───────┘
true ;
false.
问题是它不能返回true,我必须按;
,然后返回false。这反过来意味着我的prettier_print/1
规则无法正常运行。
我想我知道这足以说明这意味着:
Prolog正在回溯并尝试对我的规则进行另一种解释(如果我正确理解我的术语,看看是否还有其他任何可以统一的内容)。这找到了另一件事与它统一,但是立即失败了。是对的吗?
我希望只有一种可能的解释。如何修复我的功能呢?
感谢您的帮助,这让我感觉像个傻瓜!
答案 0 :(得分:4)
有一种方法可以看到这个,请尝试SWI-Prolog的图形跟踪器:
?- gtrace, your_goal.
跟踪器将显示创建选择点的位置,引入非确定性。在回溯时(例如,当您在顶层按SPACE或“;”时),将考虑剩余的替代条款。
答案 1 :(得分:3)
它正在“返回”true
,然后false
,因为您正在强制它使用;
回溯。由于只有一个解决方案,回溯失败。
此行为仅发生在交互式Prolog解释器中;你要编译程序或在非交互式解释器中运行它,它只会打印结果而不是“返回”任何东西。这有点类似于例如Python解释器
的行为>>> 'foo'
'foo'
回显输入的最后一个表达式的值,但仅在交互模式下。除非您输入print
语句,否则脚本不会打印任何内容。
如果您不想看到false
消息,则要么不回溯,即按Enter键而不是;
,要么使用metapredicate once/1
:
?- member(X,[1,2,3]).
X = 1 ;
X = 2 . % ENTER pressed here
?- once(member(X,[1,2,3])).
X = 1.
?-
但不要只是在程序中的任何地方这样做,因为它会改变程序的语义。
答案 2 :(得分:2)
回溯时返回true然后返回false的原因是你在条款中留下了选择点。你的应用程序流程只执行prettier_print / 2的一个子句,但prolog解释器事先不知道,所以它留下了一个选择点,然后,在回溯时,将试图查看prettier_print / 2的任何剩余子句是否会成功。
你可以“剪切”回溯,通过使用剪切(!)来承诺一个选择:
prettier_print([]).
prettier_print([Puzzle]) :- prettier_print(0, [Puzzle]).
prettier_print(0, Puzzle) :-
writeln('┌───────┬───────┬───────┐'),
!,
prettier_print(1, Puzzle).
prettier_print(4, Puzzle) :-
writeln('│───────┼───────┼───────│'),
!,
prettier_print(5, Puzzle).
prettier_print(8, Puzzle) :-
writeln('│───────┼───────┼───────│'),
!,
prettier_print(9, Puzzle).
prettier_print(12, []) :-
writeln('└───────┴───────┴───────┘'),
!.
prettier_print(N, [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9 | Puzzle]) :-
member(N, [1,2,3,5,6,7,9,10,11]), % tried this when the line below did not work
format('│ ~d ~d ~d │ ~d ~d ~d │ ~d ~d ~d │~n', [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9]),
succ(N, N1),
prettier_print(N1, Puzzle),
!.
您也可以重写您的解决方案,以便通过使用其他谓词而不是prettier_print的不同子句来保留任何选择点。这样你就不需要使用剪切:
prettier_print(Puzzle) :-
Puzzle \= [] ->
(
print_head,
print_rows(Puzzle, NRows1),
print_line,
print_rows(Puzzle, NRows1),
print_line,
print_rows(Puzzle, NRows1),
print_end
).
print_rows(Rows, NRows):-
print_row(Rows, Rows1),
print_row(Rows1, Rows2),
print_row(Rows2, NRows).
print_head:-
writeln('┌───────┬───────┬───────┐').
print_line:-
writeln('│───────┼───────┼───────│').
print_end:-
writeln('└───────┴───────┴───────┘').
print_row([Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9 | NRows], NRows) :-
format('│ ~d ~d ~d │ ~d ~d ~d │ ~d ~d ~d │~n', [Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9]).
答案 3 :(得分:0)
Augh,没关系,我是个白痴!
我首先确定了一些不成问题的东西。将prettier_print/1
更改为此:
prettier_print([]).
prettier_print(Puzzle) :- prettier_print(0, Puzzle).
使其正常工作。
我仍然想知道为什么它会返回true而不是false。如果有人可以回答,我会标记他们的答案被接受。