3

Prolog のリストから要素の最初の出現を削除しようとしています。

私のコード:

remove_first_X(X,[X|Xs],Xs). %remove X
remove_first_X(X,[Y|Xs],[Y|Xs]) :-
   remove_first_X(X,Xs,Xs).

動作しません:

?- remove_first_X(1,[1,2,3],[2,3]).
true.

?- remove_first_X(1,[2,1,3],[2,3]).
false.

助けてください!:-)

別の試みはより近いです:

remove_first_X(X,[X|Xs],Xs).
remove_first_X(X,[Y|Xs],[Y|Ys]) :-
   remove_first_X(X,Xs,Ys).

ただし、最初に出現した後に X を削除します。

?- remove_first_X(1,X,[2,1,0]).
X = [1, 2, 1, 0] ;
X = [2, 1, 1, 0] ;
X = [2, 1, 1, 0] ;
X = [2, 1, 0, 1] ;
false.
4

2 に答える 2

4

@chamini2 によって提供された実装は不純であり、根拠のない用語を扱うと論理的に不健全になる可能性があります。次の 2 つのクエリを検討してください。

?- E=1、remove_first_X(E,Xs,[2,1,0])。
E = 1、Xs = [1,2,1,0] ;
E = 1、Xs = [2,1,1,0] ;
間違い。

?- remove_first_X(E,Xs,[2,1,0]), E=1 .
E = 1、Xs = [1,2,1,0] ;
間違い。% 1 つの解がありません!

が助けてくれます! に置き換える(\=)/2dif/2、コードは論理的に純粋になります。

remove_1st_x(X,[X|Xs],Xs).
remove_1st_x(X,[Y|Xs],[Y|Ys]) :- 
    dif(X,Y),
    remove_1st_x(X,Xs,Ys).

上記のクエリをもう一度実行してみましょう。今回は改善された実装を使用します。

?- E=1、remove_1st_x(E,Xs,[2,1,0])。
E = 1、Xs = [1,2,1,0] ;
E = 1、Xs = [2,1,1,0] ;
間違い。

?- remove_1st_x(E,Xs,[2,1,0]), E=1 .
E = 1、Xs = [1,2,1,0] ;
E = 1、Xs = [2,1,1,0] ;
間違い。

その方がいいです!また、OP によって指定された他のクエリも、次のように機能します。

?- remove_1st_x(1,[1,2,3],[2,3]).
true ;
false.

?- remove_1st_x(1,[2,1,3],[2,3]).
true ;
false.

?- remove_1st_x(1,X,[2,1,0]).
X = [1,2,1,0] ;
X = [2,1,1,0] ;
false.

編集 2015-05-07

上記の実装は、remove_1st_x/3決定論的に成功する可能性がある場合に、役に立たない選択ポイントを残します。性を維持しながら、その非効率性を取り除きましょう!

質問「Prolog union for AUBUC 」への回答で@falseによって定義されているように、if_/3等式(=)/3(別名equal_truth/3)を使用して具体化すると、次のように定義できます。remove_1st_x/3

remove_1st_x(E,[X|Xs],Ys) :-
   if_(X=E, Xs=Ys, (Ys=[X|Ys0],remove_1st_x(E,Xs,Ys0))).

上記のクエリをもう一度実行してみましょう。すべてが決定論的に成功することに注意してください。

?- remove_1st_x(1,[2,1,3],Ys).
Ys = [2,3].

?- remove_1st_x(1,[2,1,3],[2,3]).
true.

?- remove_1st_x(1,[1,2,3],[2,3]).
true.
于 2015-05-04T15:21:54.837 に答える