1

問題を見つけようとしましたが、うまくいきませんでした。何が問題なのか教えていただけますか?

% using accumulator
deleteall(X,Y,Zs) :- deleteall(X,Y, [], Zs).
deleteall(X, [], Zs, Zs).
deleteall(X, [X|Xs], Xs, V).
deleteall(X, [Y|Xs], [Y|Zs], V) :- deleteall(X, Xs, Zs,V).
4

3 に答える 3

1

純粋な解決策については、この回答を検討してください。引数の順序が異なることに注意してください

しかし、あなたの実際の質問は次のとおりでした:あなたのソリューションの何が問題なのですか?

Prolog 独自の方法でこれに答える方法があります。他のプログラミング言語では、意味のあるテスト ケースを見つけ出す必要があります。次に、そのようなテスト ケースを使用して、実装が機能するかどうかを確認します。もちろんPrologでも可能です。

しかし、これらのテスト ケースを把握するための実際のコストについて考えてみてください。関係全体を詳細に理解する必要があります。精神的に存在するデータ構造に関する詳細をすべて把握する必要があります。それはかなりの知的な努力です。あなたの例は非常に単純であるため、その努力はささいなことのように見えます。しかし、あちこちに追加された詳細を想像してみてください。

では、実際の関係を理解せずに述語のテスト ケースをどのように理解できるのでしょうか。

最も一般的なクエリを取り上げます。つまり、すべての引数に個別の変数があるゴールです。あなたの例では、それはdeleteall(X, Xs, Ys). これで作業は完了し、Prolog に空白を埋めさせることができます。

?-すべて削除(X,Xs,Ys).
Xs = Ys、Ys = [] ;
Xs = [X] ;
間違い。

あなたの定義では、2 つの答えが得られます。最初の回答にはXs、空のリストになるための解決策が含まれています[]。2 番目の回答にはXs、1 つの要素リストになるための解決策が含まれています。そして、それはあなたの関係が説明するすべてです。

2 つ以上の要素を含むリストについてはどうでしょうか。それらに対する解決策はありません。したがって、あなたの定義はその点で具体的すぎます。

そして、2 番目の答えはすべての場合に当てはまりますYs。たとえばdeleteall(1,[1],[2,3])、あなたの定義によると - も成り立ちます。さらに悪いことdeleteall(1,[1],[1]).に、まったく削除されません。したがって、あなたの定義はここでは一般的すぎます。


このすべての落とし穴はどこにあるのでしょうか? そうですね、純粋で単調なプログラムを書かなければなりません。つまり、 、 、 、および副作用のあるビルトインのような不純なビルトインは!/0使用(\+)/1(\=)/2(\==)/2はなりません (または非常に特別な注意を払って使用してください)。

于 2012-05-29T08:18:19.807 に答える
0

シングルトン変数は常に疑わしいものであり、あなたの場合、 V in の意味は何deleteall(X, [X|Xs], Xs, V).ですか?

それとは別に、なぜアキュムレータを使用しているのかわかりません。

削除されていない要素を元に戻すように割り当てられていますか? それ以外の場合は、機能するdeleteallがあります...

deleteall(_, [], []).
deleteall(X, [X|Xs], Zs) :- !, deleteall(X, Xs, Zs).
deleteall(X, [Z|Xs], [Z|Zs]) :- deleteall(X, Xs, Zs).

テスト:

?- deleteall(2,[1,2,3,54,2,1,4,2],X).
X = [1, 3, 54, 1, 4] ;
false.
于 2012-05-28T14:39:28.070 に答える
0

あなたのコードから、統一に基づくすべて削除のセマンティクスが必要なようです (代わりに、(==)/2 を使用して等しい用語のみを削除することもできます)。すべてのリスト要素 (および削除する要素) は常に固定されていますか? そうしないと、削除する要素が部分的にインスタンス化され、リスト要素の 1 つと統合するときにさらにインスタンス化されるたびに、コードが失敗する可能性があります。この問題は、頭の統合の代わりに、たとえば本文の二重否定を使用することで解決できます。「chac」がすでに指摘したように、選択ポイントも残しています。カットまたは if-then-else を使用すると、その問題が解決します。コードを改善するもう 1 つの方法は、リストを最初の引数に移動して、Prolog の最初の引数のインデックス作成のパフォーマンスを向上させることです (もちろん、その述語への呼び出しでは、最初の引数がインスタンス化されます)。次の行に沿った定義に従います。

delete_all([], _, []).
delete_all([X|Xs], Y, Zs) :-
    (   \+ X \= Y ->
        delete_all(Xs, Y, Zs)
    ;   Zs = [X|Zs0],
        delete_all(Xs, Y, Zs0)
    ).
于 2012-05-28T19:06:13.800 に答える