如何为主列表中的某个元素构建一个位置列表?

时间:2015-05-29 08:47:22

标签: prolog

我如何编写一个谓词list_pos(B,E,L),它返回EB的位置,位于名为L的列表中(考虑B的第一个元素1}}有位置= 0),我尝试编写这样的程序,但它没有成功运行。谢谢

5 个答案:

答案 0 :(得分:2)

这是一个比@ Jerome更为通用的解决方案:

", "

所以你甚至不需要指出你想要的精确元素。相反,你问:

  

各种元素的出现次数是什么?

这甚至可以进一步推广......

答案 1 :(得分:2)

这是一个通用的,纯粹的解决方案 - 我将在这里放置一个赏金以使其适合更方便的抽象。

list_pos(Xs, E, Ps) :-
   list_pos(Xs, E, Ps, 0).

list_pos([], _E, [], _P).
list_pos([X|Xs], X, [P0|Ps], P0) :-
   P1 is P0 + 1,
   list_pos(Xs, X, Ps, P1).
list_pos([X|Xs], E, Ps, P0) :-
   dif(X, E),        % element must be different
   P1 is P0 + 1,
   list_pos(Xs, X, Ps, P1).

这是list_pos/4使用if_/3和重新平等(=)/3的更紧凑和有效的方法。 Prolog的if_/3与传统的if-then-else略有不同,因为它可以选择 然后 Else。也许只需试用if_/3

?- if_( X=Y, Diagnosis=equal, Diagnosis=inequal).
X = Y,
Diagnosis = equal ;
Diagnosis = inequal,
dif(X, Y).

非正式地,我们在这里问的是:

  

XY是否相等?

而Prolog的回答不仅仅是肯定或否定,而是:

  

是的,如果他们是平等的,他们是平等的

  

不,他们不平等,如果他们不同

听起来很烦人?好吧,如果我们问这些一般性问题不包含足够的信息,我们不应该对得到类似的一般答案感到惊讶!

list_pos([], _E, [], _P).
list_pos([X|Xs], E, Ps0, P0) :-
   P1 is P0+1,
   if_(X = E, Ps0 = [P0|Ps1], Ps0 = Ps1),
   list_pos(Xs, E, Ps1, P1).

现在,让我们尝试一些非常通用的东西!

  

列表[X,Y,Z]的外观必须如此,以便任何元素E出现在其中两次?

?- list_pos([X,Y,Z],E,[A,B]).
   X = Y, Y = E, % ... the first two are the same
   A = 0, B = 1,
   dif(Z, E)     % ... but the last is different
;  X = Z, Z = E, % ... the first and last are the same
   A = 0, B = 2,
   dif(Y, E)     % ... but the middle element is different
;  Y = Z, Z = E, % ... the last two are the same
   A = 1, B = 2,
   dif(X, E)     % ... and the first is different.
;  false.

请注意,这些答案包含所有可能的三个元素列表的完整通用性!所有这些都已包括在内。

答案 2 :(得分:1)

感谢@false和@Jerome,我学到了很多东西。不过,我会发布我的努力:

    list_pos(List,Elem,Result) :-
            list_pos(List,Elem,[],-1,R),
            reverse(R,Result),
            !.

    list_pos([],_,W,_,W).
    list_pos([X|Xs],X,Zs,P,R) :-
            Pos is P + 1,
            list_pos(Xs,X,[Pos|Zs],Pos,R).
    list_pos([_|Xs],Y,Zs,P,R) :-
            Pos is P + 1,
            list_pos(Xs,Y,Zs,Pos,R).

实施例

    ?- list_pos([],a,R).
    R = [].

    ?- list_pos([a,c,a,d,e,f],a,R).
    R = [0, 2].

    ?- list_pos([a,b,c,d,e,f,g],g,R).
    R = [6].

    ?- list_pos([a,a,a,a,a,a,a,a,a],a,R).
    R = [0, 1, 2, 3, 4, 5, 6, 7, 8]. 

答案 3 :(得分:0)

我试过了:

    list_pos(1,Match,[Match|_]).
    list_pos(Pos,Element,[_|Tail]) :-
             list_pos(P,Element,Tail),
             Pos is P + 1.

实施例

    ?- list_pos(B,a,[a]).
    B = 1 .

    ?- list_pos(B,a,[b,a]).
    B = 2 .

    ?- list_pos(B,a,[b,c,d,e,a,f]).
    B = 5 .

答案 4 :(得分:0)

要构建所有结果的列表,请使用findall

list_pos(List, Element, Result) :-
  findall(Position, nth0(Position, List, Element), Result).