我刚开始使用Prolog并遇到问题:
(a)给定列表L,对象X和正整数K,它返回 如果X出现至少K,则在L中出现第K次X的位置 在L中的时间,否则为0.
目标
pos([a,b,c,b],b,2,Z)
应该成功回答Z = 4
。
到目前为止,我有:
pos1([],H,K,F).
pos1([H],H,1,F).
pos1([H|T],H,K,F):- NewK is K - 1, pos1(T,H,NewK,F), F is F + 1.
pos1([H|T],X,K,F):- pos1(T,X,K,F).
但我无法弄明白为什么我会这样:
ERROR: is/2: Arguments are not sufficiently instantiated
非常感谢任何帮助!
答案 0 :(得分:1)
使用clpfd!
:- use_module(library(clpfd)).
我们根据(#>)/2
,(#=)/2
,if_/3
,dif/3
和(#<)/3
定义pos/4
:
pos(Xs,E,K,P) :-
K #> 0,
pos_aux(Xs,E,K,1,P).
pos_aux([X|Xs],E,K,P0,P) :-
P0+1 #= P1,
if_(dif(X,E),
pos_aux(Xs,E,K,P1,P),
if_(K #< 2,
P0 = P,
(K0+1 #= K,
pos_aux(Xs,E,K0,P1,P)))).
OP给出的示例查询:
?- X = b, N = 2, pos([a,b,c,b],X,N,P). X = b, N = 2, P = 4. % succeeds deterministically
以下更一般的查询怎么样?
?- pos([a,b,c,b],X,N,P). X = a, N = 1, P = 1 ; X = b, N = 1, P = 2 ; X = b, N = 2, P = 4 % (exactly like in above query) ; X = c, N = 1, P = 3 ; false.
答案 1 :(得分:0)
让我们采用高级方法,交换结果代码的效率,以便于开发:
pos(L,X,K,P):-
numerate(L,X,LN,1), %// [A1,A2,A3...] -> [A1-1,A2-2,A3-3...], where Ai = X.
( drop1(K,LN,[X-P|_]) -> true ; P=0 ).
现在我们只实现两个新的谓词。 drop1(K,L,L2)
会从K-1
中删除L
个元素,因此我们会留下L2
:
drop1(K,L2,L2):- K<2, !.
drop1(K,[_|T],L2):- K1 is K-1, drop1(K1,T,L2).
numerate(L,X,LN,I)
为I
的每个元素添加基于L
的索引,但仅保留X
s:
numerate([],_,[],_).
numerate([A|B],X,R,I):- I1 is I+1, ( A=X -> R=[A-I|C] ; R=C ), numerate(B,X,C,I1).
测试:
5 ?- numerate([1,b,2,b],b,R,1).
R = [b-2, b-4].
6 ?- pos([1,b,2,b],b,2,P).
P = 4.
7 ?- pos([1,b,2,b],b,3,P).
P = 0.
答案 2 :(得分:0)
我已经更正了你的代码而没有改变逻辑,这似乎已经很简单了。 刚刚添加了一个“顶级”处理程序,传递给实际工作者pos1 / 4并测试是否有效,否则返回0 - 在Prolog中有争议的方式,imo最好允许失败,我希望你会欣赏如何采用这个(见注释) )简化了你的代码...
pos(L,X,K,F):- pos1(L,X,K,F) -> true ; F=0.
% pos1([],H,K,F). useless: let it fail
% pos1([H],H,1,F). useless: already handled immediatly bottom
pos1([H|T],H,K,P):- K==1 -> P=1 ; NewK is K - 1, pos1(T,H,NewK,F), P is F + 1.
pos1([_|T],X,K,P):- pos1(T,X,K,F),P is F+1.
我希望您可以使用if / then / else结构。无论如何,收益率
7 ?- pos([a,b,c,b],b,2,Z).
Z = 4.
8 ?- pos([a,b,c,b],b,3,Z).
Z = 0.
答案 3 :(得分:0)
像这样的东西。外部谓词(这个强制执行指定的约束)调用内部工作者谓词:
kth( L , X , K , P ) :-
is_list( L ) , % constraint: L must be a list
nonvar(X) , % constriant: X must be an object
integer(K) , K > 0 % constraint: K must be a positive integer
kth( Ls , X , K , 1 , P ) % invoke the worker predicate with its accumulator seeded to 1
. % easy!
is_list/2
确保您有一个列表:
is_list(X) :- var(X) , !, fail .
is_list([]).
is_list([_|_]).
完成所有工作的谓词就是这个:
kth( [] , _ , _ , _ , 0 ) . % if we hit the end of the list, P is 0.
kth( [X|Ls] , X , K , K , K ) :- ! . % if we find the Kth desired element, succeed (and cut: we won't find another Kth element)
kth( [_|Ls] , X , K , N , P ) :- % otherwise
N < K , % - if we haven't got to K yet ...
N1 is N+1 , % - increment our accumulator , and
kth(Ls,X,K,N1,P) % - recurse down.
. % easy!
虽然回答0而不是失败的概念不是Prolog Way,如果你问我。