3

リスト内の要素の出現をカウントしたいのですが、存在する場合は一意の述語が真になり、そうでない場合は偽になります。ただし、要素が複数回出現する場合、Prolog はそれが true であると判断します。どうすればいいのかわからない...

count([], X, 0).
count([X|T], X, Y) :- count(T, X, Z), Y is 1+Z, write(Z).
count([_|T], X, Z) :- count(T, X, Z).

unique(St, [Y|RestList]) :- count([Y|RestList], St, N), N =:= 1.
4

2 に答える 2

4

最初の引数がグラウンド リストである限り、ソリューションは機能します。他のいくつかのケースでは、それは正しくありません:

?- count([E], a, 0).
false.

ここでお願いします

長さ 1 のリストの要素Eは、リストに 0 の出現が含まれるようにどのように見える必要がありaますか?

E = bそして実際には、またはのような答えがありますE = c

?- count([b],a,0).
true.

?- count([c],a,0).
true.

このため、Prolog の回答は不完全でした。はい、と言うべきでした。しかし、どのように?

count([], _, 0).
count([E|Es], F, N0) :-
   count(Es, F, N1),
   if_(E = F, D = 1, D = 0),
   N0 is N1+D.

これはif_/3とを使用し(=)/3ます。

?- length(Xs, I), count_dif(Xs, a, N).
   Xs = [],
   I = N, N = 0
;  Xs = [a],
   I = N, N = 1
;  Xs = [_A],
   I = 1,
   N = 0,
   dif(_A, a)
;  Xs = [a, a],
   I = N, N = 2
;  Xs = [_A, a],
   I = 2,
   N = 1,
   dif(_A, a) ;
   Xs = [a, _A],
   I = 2,
   N = 1,
   dif(_A, a) ;
   Xs = [_A, _B],
   I = 2,
   N = 0,
   dif(_A, a),
   dif(_B, a)
...

これをさらに改善するためにlibrary(clpfd)、SICStus、YAP、および SWI で利用可能なものを使用する可能性があります。

:- use_module(library(clpfd)).

count([], _, 0).
count([E|Es], F, N0) :-
   N0 #>= 0,
   if_(E = F, D = 1, D = 0),
   N0 #= N1+D,
   count(Es, F, N1).

現在、以下も終了します。

?- count([a,a|_], a, 1).
false.

?- N #< 2, count([a,a|_], a, N).
false.
于 2015-03-10T18:40:13.323 に答える
1

独自の句を使用して、プログラムを少し最適化します。

  • シングルトン変数を無名変数に置き換える
  • カウント述語の 2 番目の句にカットを追加します
  • unique 句の 2 番目の条件を削除します。

これは今のプログラムです:

count([],_,0).

count([X|T],X,Y):- !, count(T,X,Z), Y is 1+Z.

count([_|T],X,Z):- count(T,X,Z).

unique(St,L):- count(L,St,1).

相談する:

?- count([2,3,4,3], 3,N).
N = 2.

?- unique(3, [2,3,4,5]).
true.
于 2015-03-09T23:32:26.220 に答える