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 は後戻りして、私のルールの別の解釈を試みています (私の用語を正しく理解していれば、統一できるものが他にないかどうかを調べます)。これはそれと統合する別のものを見つけますが、すぐに失敗します。そうですか?

可能な解釈は1つだけであってほしい。それを意味するように関数を修正するにはどうすればよいですか?

助けてくれてありがとう、これは私がそのようなばかのように感じています!

4

4 に答える 4

4

これを確認する1つの方法として、SWI-Prologのグラフィカルトレーサーを試してください。

?- gtrace, your_goal.

トレーサーは、選択ポイントが作成された場所を示し、非決定論を導入します。バックトラック時に(たとえば、トップレベルでSPACEまたは ";"を押すと)、残りの代替句が考慮されます。

于 2011-04-12T07:21:53.570 に答える
3

でバックトラックを強制しているためtrue、それは「戻る」です。解が 1 つしかないため、後戻りは失敗します。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.

?- 

ただし、プログラムのセマンティクスが変更されるため、プログラムのどこかでそれを行うだけではいけません。

于 2011-04-12T12:00:07.707 に答える
2

バックトラック時に true を返し、次に false を返す理由は、句に選択ポイントを残しているためです。アプリケーション フローは prettier_print/2 の 1 つの句のみを実行しますが、プロローグ インタープリターは事前にそれを認識していないため、選択ポイントを残し、バックトラック時に、prettier_print/2 の残りの句のいずれかが実行されるかどうかを確認しようとします。成功した。

カット (!) を使用して、バックトラッキングを「カット」し、1 つの選択にコミットすることができます。

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 に答える