计算Prolog中特定对象元素的数目

计算Prolog中特定对象元素的数目,prolog,Prolog,我的代码可以很好地处理数字,但不能处理对象类型 计数(u,[],0)。 计数(字段[Field | Tail],N):- 计数(字段、尾部、N1), N是N1+1。 计数(字段[H|Tail],N):- 字段\=H, 计数(字段、尾部、N)。 ?-计数(1[1,2,3],X)。 X=1.%好啊 -计数(1,[1,2,3,1],X)。 X=2.%好啊 -计数(元素(温度,u),[元素(温度,值1),元素(温度,值2)],X)。 X=1.%我以为这里有两个。 对于最后一行,我期望X=2,因为

我的代码可以很好地处理数字,但不能处理对象类型

计数(u,[],0)。
计数(字段[Field | Tail],N):-
计数(字段、尾部、N1),
N是N1+1。
计数(字段[H|Tail],N):-
字段\=H,
计数(字段、尾部、N)。
?-计数(1[1,2,3],X)。
X=1.%好啊
-计数(1,[1,2,3,1],X)。
X=2.%好啊
-计数(元素(温度,u),[元素(温度,值1),元素(温度,值2)],X)。
X=1.%我以为这里有两个。
对于最后一行,我期望
X=2
,因为

  • elem(temp,u)=elem(temp,val1)
  • elem(temp,u)=elem(temp,val2)
我的问题是:

  • 问题1。为什么它不起作用
  • 问题2。我怎样才能使它适用于任何类型

谢谢。

您的代码不起作用,因为
elem(temp,)
与列表的第一项统一,并且统一在递归调用中传播。您可以通过跟踪执行来观察这一点

?- trace, count(elem(temp, _), [elem(temp, val1), elem(temp, val2)], X).
   Call: (11) count(elem(temp, _30894), [elem(temp, val1), elem(temp, val2)], _30926) ? creep
   Call: (12) count(elem(temp, val1), [elem(temp, val2)], _31518) ? creep
   Call: (13) elem(temp, val1)\=elem(temp, val2) ? creep
   Exit: (13) elem(temp, val1)\=elem(temp, val2) ? creep
   Call: (13) count(elem(temp, val1), [], _31650) ? creep
   Exit: (13) count(elem(temp, val1), [], 0) ? creep
   Exit: (12) count(elem(temp, val1), [elem(temp, val2)], 0) ? creep
   Call: (12) _30926 is 0+1 ? creep
   Exit: (12) 1 is 0+1 ? creep
   Exit: (11) count(elem(temp, val1), [elem(temp, val1), elem(temp, val2)], 1) ? creep
X = 1 .
要使其工作,可以使用谓词:

因此,一种可能的解决办法是:

count(_, [], 0).

count(Field, [First|Tail], N) :-
   subsumes_term(Field, First),
   count(Field, Tail, N1),
   N is N1 + 1.

count(Field, [First|Tail], N) :-
  not(subsumes_term(Field, First)),
  count(Field, Tail, N).
运行示例:

?- count(1, [1,2,3], X).
X = 1 ;
false.

?- count(1, [1,2,3,1], X).
X = 2 ;
false.

?- count(elem(temp, _), [elem(temp, val1), elem(temp, val2)], X).
X = 2 ;
false.
效率更高的版本是:

count(Field, List, Count) :-
   count(List, Field, 0, Count).

count([], _, Acc, Acc).

count([First|Tail], Field, Acc, Count) :-
   (   subsumes_term(Field, First)
   ->  Acc1 is Acc + 1
   ;   Acc1 is Acc ),
  count(Tail, Field, Acc1, Count).

A1。它不起作用,因为
\uu
被映射到单个值(
\uu=val1
)。一旦映射了
val1
val2
就不再匹配了。谢谢!我意识到它为什么不起作用,但却找不到一种方法使它起作用。这太神奇了。
count(Field, List, Count) :-
   count(List, Field, 0, Count).

count([], _, Acc, Acc).

count([First|Tail], Field, Acc, Count) :-
   (   subsumes_term(Field, First)
   ->  Acc1 is Acc + 1
   ;   Acc1 is Acc ),
  count(Tail, Field, Acc1, Count).