我上次了解= ..可以将列表翻译成术语和相反术语。 我有3个谓词,第一个是将列表翻译成术语的谓词。我想出了这样的东西:
list_to_term(List, Functor, Term) :-
Term =.. [Functor | List].
好吗?足够?还是我想念什么?
元素A的另一个谓词是count(A,T,N)
,条件T中的元素N为N,如果N是元素T中元素A的数量,则为真。 ?
?- count(a,f(a),N).
N = 1
?- count(a,f(a,g(b,a),N).
N = 2.
?- count(a,f(a,g(X,a),N).
N = 2.
答案 0 :(得分:1)
看看the answer of this post,您可以重用谓词flatten_term/2
,并对其进行一些修改以处理自由变量,以解决问题。这是基本解决方案的代码:
flatten_term(Term,[Term]):-
(atomic(Term);var(Term)),!.
flatten_term(Term,Flat):-
Term =.. TermList,
flatten_term_list(TermList,Flat),!.
flatten_term_list([],[]):-!.
flatten_term_list([H|T],List):-
flatten_term(H,HList),
flatten_term_list(T,TList),
append(HList,TList,List),!.
occurrences(_,[],N,N):-!.
occurrences(A,[H|T],N,Tot):-
A \== H,!,
occurrences(A,T,N,Tot).
occurrences(A,[H|T],N,Tot):-
A == H,!,
N1 is N+1,
occurrences(A,T,N1,Tot).
count(A,Term,N):-
flatten_term(Term,Flatten),
occurrences(A,Flatten,0,N).
?- count(a,f(a,g(X,a),d),T).
T = 2.
?- count(X,f(a,g(X,a),d),T).
T = 1
首先,您使用flatten_term/2
将术语展平。然后只需使用occurrences/4
计算要查找的元素的出现次数即可。您可以根据需要修改flatten_term/2
以避免使用occurrences/4
,因此只扫描术语(列表)一次...类似flatten_term(Term,Flatten,ElementToFind,Counter,Total)
。
答案 1 :(得分:1)
首先解决一个更普遍的问题,即对列表中的项进行计数。毕竟,处理术语是处理包含该术语的单例列表:
count(A,T,N):- count(A, [T|Z],Z, 0,N).
count(_, [], [], C,N):- N is C, !.
count(A, [T|B],Z, C,N):- ?=(A,T), A=T, !, count(A, B,Z, C+1,N).
count(A, [T|B],Z, C,N):- ?=(A,T), T=..[_|S], !, append(S,Y,Z), count(A, B,Y, C,N).
count(A, [_|B],Z, C,N):- count(A, B,Z, C,N).
这将依次打开 list 中的每个主术语,并将其自变量项附加到该 list ,从而将其用作 queue 。 ..因此以 breadth-first 的方式处理谓词的第二个自变量T
。
这假设A
参数是一个原子,而?=
用于避免实例化我们可能遇到的自由变量,而是跳过它们,如您的示例所示。
答案 2 :(得分:0)
好吗?足够?还是我想念什么?
Prolog的=../2
predicate [swi-doc]可以“打包”和“解包”一个列表,该列表包含术语中的函子名称及其参数,反之亦然。因此,可以使用它来构造一个术语,或分析一个术语。例如:
?- f(a,g(b,a)) =.. L.
L = [f, a, g(b, a)].
此处f
是函子名称,a
和g(b, a)
是自变量。这些参数也可以是术语,因此我们需要进一步解开这些参数。
例如,我们可以使用以下方法获得一个术语的所有子术语:
subterms(T, T) :-
\+ var(T).
subterms(T, ST) :-
\+ var(T),
T =.. [_|As],
member(A, As),
subterms(A, ST).
例如:
?- subterms(f(a,g(X,a)),N).
N = f(a, g(X, a)) ;
N = a ;
N = g(X, a) ;
N = a ;
false.
现在我们获得了所有(子)项,我们可以将谓词略微重写为 count 匹配的元素数:
subterm_query(Q, T) :-
Q == T.
subterm_query(Q, T) :-
\+ var(T),
T =.. [_|As],
member(A, As),
subterm_query(Q, A).
这样我们就可以查询a
:
?- subterm_query(a, f(a,g(X,a))).
true ;
true ;
false.
如果我们可以使用aggregate
library,则可以利用aggregate_all/3
predicate来计数谓词成功的次数:
?- aggregate_all(count, subterm_query(a, f(a,g(X,a))), Count).
Count = 2.
如果不是,则需要实现一种机制,该机制返回1
进行匹配,然后递归地总结子项的匹配。我将其保留为练习。