序言 - 尾递归问题

时间:2014-03-17 23:57:01

标签: list recursion prolog tail-recursion

我是prolog的新手,我正在尝试创建一个谓词并且遇到了一些麻烦。

我列出了通过火车相连的城市。它们通过我的links / 2子句连接。

links(toronto, ajax).
links(toronto, markham).
links(toronto, brampton).
links(brampton, markham).
links(markham, ajax).
links(brampton, mississauga).
links(mississauga, toronto).
links(mississuaga, oakville).
links(oakville, st.catharines).
links(oakville, hamilton).
links(hamilton, st.catharines).

我正在编写一个名为addnewcities的谓词,它将获取一个城市列表,然后返回一个包含原始列表的新列表,以及与原始列表中每个城市直接相连的所有城市。

这是链接的(粗略看)可视化表示。 enter image description here

如果我的输入列表是[toronto],我希望我的输出为(顺序无关紧要)[ajax,markham,brampton,mississauga,toronto]

如果输入为[oakville,hamilton],我希望输出为[mississauga,st.catharines,oakville,hamilton]

到目前为止,这是我的谓词。

addnewcities([],_).
addnewcities([CitiesH|Tail],Ans):- directer(CitiesH,Ans2),  merger(Ans2,[CitiesH],Ans), addnewcities(Tail,Ans).

directer/2占用一个城市并保存一个包含第二个arg中所有直接连接城市的列表。

merger/3只需合并两个列表,确保最终列表中没有重复项。

当我的输入是一个包含一个元素的列表,即[toronto]时它就可以了! 但是当我有一个包含多个元素[toronto,ajax]的列表时,它每次都会显示“false”。

我很确定我的问题是,当它第二次递归时,合并就是它的错误。我只是不知道如何解决这个问题,以便我的列表可以保持更新,而不是被检查是真还是假。

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

此查询使用库支持来解决问题:

addcities(Cs, L) :-
  setof(D, C^(member(C,Cs), (C=D;link(C,D);link(D,C))), L).

答案 1 :(得分:1)

这应该适用于你想要的东西:

addcities(A,B):-
    addcitiesaux(A,[],B).

addcitiesaux([],X,X).

addcitiesaux([X|Xs],L,R):-
    link(X,A),
    \+ member(A,L),
    !,
    addcitiesaux([X|Xs],[A|L],R).

addcitiesaux([X|Xs],L,R):-
    link(A,X),
    \+ member(A,L),
    !,
    addcitiesaux([X|Xs],[A|L],R).

 addcitiesaux([X|Xs],L,R):-
    addcitiesaux(Xs,[X|L],R).