首页 > 解决方案 > 在 Prolog 中复制 findall

问题描述

我试图让一些代码返回一个位置/索引列表,其中元素在某个基本列表中找到。经过大量搜索、复制、调整等。以下代码是我到目前为止所得到的。

它可以在 SWISH 中使用,但需要我点击下几次才能最终获得一个包含搜索元素所有位置的列表。

在发送/打印回结果列表之前,我如何让它完成所有答案?

pos([E|_],E,I,P) :-  P = I.
pos([E|T],E,I,[P|Pt]) :- I1 is I+1, pos(T,E,I1,Pr), Pt = Pr, P = I.
pos([H|T],E,I,P) :- H\=E, I1 is I+1, pos(T,E,I1,Pr), P = Pr.

find(X,P):- a(L),pos(L,X,1,Pr), P = Pr.

a([2,1,4,5,3,2,6,2,1,21,2,1,4,7,4,3,5,2,4,6,8,2,1,37,3,2]).

结果:

?- find(2,X)
X = 1
X = [1|6]
X = [1, 6|8]
X = [1, 6, 8|11]
X = [1, 6, 8, 11|18]
X = [1, 6, 8, 11, 18|22]
X = [1, 6, 8, 11, 18, 22|26]

标签: prolog

解决方案


有几种可能的解决方案。如果你想保留你的代码,你应该写这样的东西(基本上,你确实需要在找到匹配项时再次调用谓词)

find_in([],_,_,[]).
find_in([El|TL],El,Pos,[Pos|T]):- !,
    P1 is Pos + 1,
    find_in(TL,El,P1,T).
find_in([_|T],El,Pos,L):-
    P1 is Pos + 1,
    find_in(T,El,P1,L).

find_pos(El,LPos):-
    a(L),
    find_in(L,El,1,LPos).

?- find_pos(2,X).
X = [1, 6, 8, 11, 18, 22, 26]

我已经使用了切割,但你可以避免使用它\=(就像你在你的问题中所做的那样)。如果您可以使用内置谓词(nth0/3或类似的东西 and findall/3),有一个更紧凑的解决方案:

find_pos(El,LPos):-
    a(L),
    findall(I,nth1(I,L,El),LPos).

?- find_pos(2,X).
X = [1, 6, 8, 11, 18, 22, 26]

推荐阅读