Recursion 序言:映射到列表的ID号

Recursion 序言:映射到列表的ID号,recursion,prolog,counter,Recursion,Prolog,Counter,我有一个变量X,它可能包含多个值:X=1;X=4;X=7 这些值映射到包含x、y、z或w的列表。这些值/列表对中的每一个都被拆分为多个事实,因此我可以: map(2,[x,y]). map(3,[x]). map(9,[y,w]). 我试图写一个程序,给定X,我可以查找这些列表,并计算X,y,z或w的出现次数 这是我的尝试: count(A,B,C,D,X) :- A = 0, B = 0, C = 0, D = 0, check_list(X,x,A)

我有一个变量X,它可能包含多个值:X=1;X=4;X=7

这些值映射到包含x、y、z或w的列表。这些值/列表对中的每一个都被拆分为多个事实,因此我可以:

map(2,[x,y]).
map(3,[x]).
map(9,[y,w]).
我试图写一个程序,给定X,我可以查找这些列表,并计算X,y,z或w的出现次数

这是我的尝试:

count(A,B,C,D,X) :- A = 0, B = 0, C = 0, D = 0,
                    check_list(X,x,A), 
                    check_list(X,y,B), 
                    check_list(X,z.C), 
                    check_list(X,w,D).

check_list(X,Element,Counter) :- 
                                 map(X, List),
                                 member(List, Element), 
                                 S is Counter + 1, 
                                 Counter = S.

我的程序背后的想法是调用check_list来检查是否有一个成员包含x,y,z,w,对于x的每个可能值。如果有该成员,我将递增计数器。然后我希望A、B、C、D的值有A=x的出现次数,B=y的出现次数,等等。

您使用的Prolog变量是错误的。变量实例化后不能更改其值,除非Prolog回溯到实例化之前的选择点。例如,在
count/5
规则中,将
A
统一为零,然后期望满足
检查列表(X,X,A)
A
绑定到
X
的出现次数,但
A
在该点不是自由变量

因此,您必须从第一条规则中删除
A=0,…,D=0

接下来,需要一个谓词,该谓词可用于查找列表中元素的出现次数。您可以使用
findall/3
进行以下操作:

occurrences(X, List, N):- findall(_, member(X, List), O), length(O, N).
或者你可以自己写:

occurrences(_, [], 0).
occurrences(X, [X|Tail], N):-!, occurrences(X, Tail, N1), N is N1 + 1.
occurrences(X, [_|Tail], N):-occurrences(X, Tail, N).