Prolog 如何找到从第一个和第二个列表中收集的第三个列表中的最后一项?

Prolog 如何找到从第一个和第二个列表中收集的第三个列表中的最后一项?,prolog,Prolog,此代码从第一个和第二个列表中生成第三个列表 intersection([],L1,L2,L3). intersection([H|T],L2,L3,[H|L4]):-member(H,L2),intersection(T,L3,L3,L4). member(H,[H|T]). member(X,[H|T]):-member(X,T). 这段代码查找列表中的最后一项。 我的问题是,我不知道如何使这两段代码合二为一。也就是说,程序应该在第一个和第二个列表中找到重复的元素,并在第三个列表中显示它们,

此代码从第一个和第二个列表中生成第三个列表

intersection([],L1,L2,L3).
intersection([H|T],L2,L3,[H|L4]):-member(H,L2),intersection(T,L3,L3,L4).
member(H,[H|T]).
member(X,[H|T]):-member(X,T).
这段代码查找列表中的最后一项。

我的问题是,我不知道如何使这两段代码合二为一。也就是说,程序应该在第一个和第二个列表中找到重复的元素,并在第三个列表中显示它们,然后从第三个列表中显示最后一个元素乘以3。

主要问题是
交点/4
。我假设您想要编写一个确定性谓词
intersection/3
,它的前两个参数在调用时被完全实例化,最后一个参数是输出参数。所谓确定性,我的意思是,
intersection/3
应该只成功一次,没有剩余的选择点。SWI Prolog文档包含一系列确定性和模式声明(尽管它没有强制执行它们)

在列表的归纳定义之后,首先编写谓词的声明性规范非常有用:

  • []
    Ys
    的交点是
    []
  • 如果
    A
    Ys
    的成员,则
    [A | Xs]
    Ys
    的交集前面是
    A
  • 如果
    A
    不是
    Ys
    的成员,则
    [A | Xs]
    Ys
    的交点就是
    Xs
    Ys
    的交点
  • 本规范到标准序言的最简单翻译为:

    last([U],U).
    last([_|L3],U) :- last(L3,U).
    
    如果对
    成员/2
    的第一次调用成功,则第二次调用应失败。为了避免回溯,将当前目标与第二个子句的开头统一起来,并执行对
    member/2
    的冗余调用,我们在第二个子句中出现
    member/2
    后放置一个cut

    intersection([],_,[]).
    intersection([A|Xs],Ys,[A|Zs]) :-
        member(A,Ys),
        intersection(Xs,Ys,Zs).
    intersection([A|Xs],Ys,Zs) :-
        \+ member(A,Ys),
        intersection(Xs,Zs).
    
    如果当前目标与第一个条款的标题一致,它将不会与后面条款的标题一致。为了防止虚假回溯,我们在第一个子句的(空)正文中放置了一个切口。这个切割是否必要取决于Prolog实现的类型

    intersection([],_,[]).
    intersection([A|Xs],Ys,[A|Zs]) :-
        member(A,Ys),
        !,
        intersection(Xs,Ys,Zs).
    intersection([_|Xs],Ys,Zs) :-
        intersection(Xs,Ys).
    
    我们只对第二份名单中的会员资格感兴趣。因此,我们可以用半确定性谓词替换
    member/2
    的出现。这里,半确定性意味着
    memberchk/2
    只成功或失败一次,没有剩余的选择点

    intersection([],_,[]) :-
        !.
    intersection([A|Xs],Ys,[A|Zs]) :-
        member(A,Ys),
        !,
        intersection(Xs,Ys,Zs).
    intersection([_|Xs],Ys,Zs) :-
        intersection(Xs,Ys).
    
    intersection/3
    的此实现与SWI Prolog库中的实现几乎相同。您可以将此谓词与
    last/2
    的实现相结合,以完成您的程序。例如:

    intersection([],_,[]).
        !.
    intersection([A|Xs],Ys,[A|Zs]) :-
        memberchk(A,Ys),
        !,
        intersection(Xs,Ys,Zs).
    intersection([_|Xs],Ys,Zs) :-
        intersection(Xs,Ys).
    
    在此,我建议您执行以下操作:

  • 使用like执行
    交叉口/3
  • 读给我听
  • 读给我听

  • 他们正在做的事情比我在这个答案中尝试的要有趣和复杂得多。

    intersection/4
    肯定是错误的。此外,有4个论点,也没有3个论点
    last_duplicate_tripled(Xs,Ys,N) :-
        intersection(Xs,Ys,Zs),
        last(Zs,M),
        N is M * 3.