2

编辑:为什么我是个傻瓜,请参阅下面的答案。不过,这里面还有一个谜,我很想回答。

我已经被困在这太久了。我正在尝试在漂亮的网格中打印出数独解决方案。

我想我遇到了问题,因为我不了解模式匹配在 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 正在回溯并尝试对我的规则进行另一种解释(如果我正确理解我的条款,看看是否还有其他可以统一的东西)。这找到了另一件事与之统一,但这立即失败了。是对的吗?

我希望只有一种可能的解释。我怎样才能修复我的功能意味着这个?

谢谢你的帮助,这让我觉得自己像个傻瓜!

4

4 回答 4

4

要查看这一点,请尝试 SWI-Prolog 的图形跟踪器:

?- gtrace, your_goal.

跟踪器将向您展示创建选择点的位置,从而引入非确定性。在回溯时(例如,当您在顶层按 SPACE 或“;”时),将考虑剩余的替代子句。

于 2011-04-12T07:21:53.570 回答
3

true那么,它正在“返回” false,因为您正在强迫它回溯;。由于只有一种解决方案,因此回溯失败。

这种行为只发生在交互式 Prolog 解释器中;如果您要编译程序或在非交互式解释器中运行它,它只会打印结果而不“返回”任何内容。这有点类似于 Python 解释器的行为

>>> 'foo'
'foo'

它与输入的最后一个表达式的值相呼应,但仅在交互模式下。print除非您输入语句,否则脚本不会打印任何内容。

如果您不想看到该false消息,请不要回溯,即按 Enter 而不是;,或使用元谓词once/1

?- member(X,[1,2,3]).
X = 1 ;
X = 2 .    % ENTER pressed here

?- once(member(X,[1,2,3])).
X = 1.

?- 

但不要只在程序的任何地方这样做,因为它会改变程序的语义。

于 2011-04-12T12:00:07.707 回答
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]).
于 2011-04-12T14:56:49.613 回答
0

哎呀,没关系,我是个白痴!

我首先指出了一些不是问题的东西。更改prettier_print/1为:

prettier_print([]).
prettier_print(Puzzle) :- prettier_print(0, Puzzle).

使它工作正常。

我仍然想了解为什么它会返回 true ,然后返回 false 。如果有人可以回答,我会将他们的回答标记为已接受。

于 2011-04-12T06:59:14.513 回答