-2
eight(A,B):-
    eight(A,[],B).

eight([],X,X).
eight([A|B],C,X):-
    eight(B,[A|C],X).

クエリ

?- eight([a,b,c],X)
4

2 に答える 2

1

eightそこに書いた述語はリストを反転します。さまざまなリストを試してみて、結果を確認するだけで、これを見つけることができたはずです。

不思議な方向へ転がる

私が理解しているように、実行すると、 にeight([a,b,c],X).一致する最初/唯一の述語が見つかりeight/2、 と統合され、おそらく. 次に、述語の本体を次のように呼び出します。[a,b,c]AX_G1234

eight([a,b,c], [], _G1234)

これは、引数を統一できる述語をチェックします。空のリストを と統合できないため、 2 番目の述語 ( ) を[a,b,c]見つけて 、 と統合し、不明な変数をそのまま渡します。次に、新しく統合された変数を使用して述語の本体を次のように呼び出します。eight/3eight([A|B],C,X)[A|B][a|[b,c]]C[]

eight([b,c], [a|[]], _G1234)

これは、引数を統一できる述語を再度チェックします。繰り返しますが、空のリストは と統合できないため、2 番目の述語を再度[b,c]見つけて、 、 と統合し、未知の変数を再び渡します。したがって、この述語の本体を次のように呼び出します。eight/3[A|B][b|[c]]C[a|[]]

eight([c], [b|[a|[]]], _G1234)

もう一度、引数を統合できる述語をチェックします。繰り返しになりますが、引数を統合できる最初の述語は、2 番目のeight/3述語です。それで、それは 、と統合[A|B][c|[]]、その未知のものを再び通過させます。本体を次のように呼び出します。C[b|[a|[]]]

eight([], [c|[b|[a|[]]]], _G1234)

統合できる述語をチェックすると、最初の述語が見つかりますeight/3。プロローグに関する限り、両方の位置に配置されている が1 つしかないため、空のリストを空のリストとX統合します。したがって、この場合は が と統一されてしまいます。最終的には次のようになります。[c|[b|[a|[]]]]X_G1234X[c|[b|[a|[]]]]

eight([], [c|[b|[a|[]]]], [c|[b|[a|[]]]])

簡単にするために、これらのリストを次のように簡略化します。

eight([], [c,b,a], [c,b,a])

アップ述語

この述語には本体がないため、実際には事実です。事実が統一されたとき、有効な解決策が見つかったと見なされます。そのため、プロローグは、決定点に到達して有効なゴールが表示されるまで、チェーンのバックアップを開始します。前の述語 asに移動しeight([c], [b,a], [c,b,a])、次に再び as eight([b,c], [a], [c,b,a])、再び as 、最後に述語 aseight([a,b,c], [], [c,b,a])の句で開始した場所に移動します。したがって、クエリを提示したときに元のものが正常に統合されました。これを次のように表示します。eight/2eight([a,b,c], [c,b,a])X

X = [c, b, a].

プログラムには他に意思決定ポイントがないため、これが唯一可能な目標であり、さらにクエリを実行するために制御が返されます。

将来、述語がどのように機能するかを知りたい場合は、トレースをオンにします。swi-pl を使用するとtrace\0、repl の述語だけになります。

于 2013-05-11T22:21:32.790 に答える