List 在prolog中相交2个列表
我的任务是在prolog中将两个列表相交。然而,我似乎找不到我的功能不工作的原因。我不知道prolog想从我这里得到什么。这是我试图解决的任务:List 在prolog中相交2个列表,list,prolog,List,Prolog,我的任务是在prolog中将两个列表相交。然而,我似乎找不到我的功能不工作的原因。我不知道prolog想从我这里得到什么。这是我试图解决的任务: write_list([]). write_list([Head|Tail]) :- write(Head), nl, write_list(Tail). intersect(L,[],X) :- write_list(X). intersect([],L,X) :- write_list(X). intersect([H1|T1],[
write_list([]).
write_list([Head|Tail]) :-
write(Head), nl,
write_list(Tail).
intersect(L,[],X) :- write_list(X).
intersect([],L,X) :- write_list(X).
intersect([H1|T1],[H2|T2], X) :-
H1 == H2,
append([H1],X,Y),
intersect(T1,T2,Y).
intersect([H1|T1],[H2|T2], X) :-
H1 > H2,
intersect(T1,[H2|T2],X).
intersect([H1|T1],[H2|T2], X) :-
H1 < H2,
intersect([H1|T1],T2,X).
write_列表([])。
写下列表([Head | Tail]):-
写(头),nl,
写下清单(尾部)。
相交(L,[],X):-写入列表(X)。
相交([],L,X):-写入列表(X)。
相交([H1 | T1],[H2 | T2],X):-
H1==H2,
附加([H1],X,Y),
相交(T1,T2,Y)。
相交([H1 | T1],[H2 | T2],X):-
H1>H2,
相交(T1[H2 | T2],X)。
相交([H1 | T1],[H2 | T2],X):-
H1
我试着把它叫做intersect([1,2,3],[2,3,4],X)。我得到的答案是[]
。谁能告诉我为什么
更新1:另一个附带问题是,我如何在不调用write_list(X)的情况下让prolog打印X。我看到一些函数返回额外的参数…让我们用逻辑语言来思考这个问题。
intersect(X,Y,Z)
的意思可能是,Z
是X
和Y
的交集。因此,intersect(L,[],X):-write_list(X)的基本情况是不正确的,除非X=[]
。对于基本情况,我们可以说:
intersect([], _, []).
因为任何东西(
)与空集([]
)相交都是空的
对于递归情况,您有:
intersect([H1|T1],[H2|T2], X) :-
H1 == H2,
append([H1],X,Y),
intersect(T1,T2,Y).
让我们稍微简化一下,因为我们可以将列表头的统一放在谓词的头中,并且我们不需要append
,因为append([H1],X,Y)
与,[H1 | X]=Y
:
intersect([H|T1],[H|T2], X) :-
intersect(T1, T2, [H|X]).
我们已经遇到了一些麻烦,因为递归调用的结果应该是较短的列表。它的意思可能是:
intersect([H|T1],[H|T2], [H|X]) :-
intersect(T1, T2, X).
但即便如此,尽管有所改进,但它还是假设相同的元素将在两个列表中相互串联,而事实可能并非如此
另一种方法是使用member/2
和delete/3
:
intersect([], _, []).
intersect([H|X], Y, Z) :-
member(H, Y)
-> delete(Y, H, Y1),
intersect(X, Y1, Z1),
Z = [H|Z1]
; intersect(X, Y, Z).
这里,如果第一个列表的当前头是第二个列表的成员,我们将从第二个列表中删除该元素的所有引用,并确定该结果与第一个列表的其余部分的交集,这将成为子句结果的尾部。否则,我们将第一个列表的尾部与第二个列表的尾部相交
请注意,这是解决问题的一种有点必要(可能有点幼稚)的方法,在必要的意义上起作用,“给定两个列表X和Y,找到它们的交点”。但它不是关系式或声明式的(“Z是X和Y的交集”),这将是Prolog的真正优势
至于您关于避免“写入”结果的问题,您可以看到,当您在prolog中执行谓词时,它将向您显示使其成为真的变量的可能实例。因此无需编写。当递归返回到空列表时,您没有基本情况。相交([],X,…)
或相交(X,[],…)
的结果是什么?在您的示例中,您的结果不仅是[]
,而且如果列表长度不同,它将完全失败。还有几个旁注:append([H1],X,Y)
可以简化为,[H1 | X]=Y
,您可以使用dif(H1,H2)
而不是单独检查H1
和H2
。使用dif/2
也可以对非数字元素起作用。啊,你说得对,当我出于愤怒而删除这些案例时,我也删除了这些案例。这是我的更新代码。结果是一样的:[]基本情况是错误的。你必须考虑intersect(X,Y,Z)
的含义,也就是说,Z
是X
和Y
的交集。当然,X
不是L
和[]
的交叉点,除非X=[]
。递归将“展开”以给出结果。你的基本情况是在所有“退绕”发生之前发生的情况。只需调用intersect([1,2,3],[2,3,4],X)即可避免write
。
和prolog将告诉您X
是什么。相交(L,[],[])。因为在这种情况下,X应该具有的值是[]?或者只是intersect([],[uu,[])
和intersect([uu,[],[])
,因为您不关心L
是什么。你的主要案例需要重新配置,因为它在逻辑上是不正确的。如果Y
是[H1 | X]
(这是您通过附加
得到的,那么Y
不一定也是T1
和T2
交叉的结果,因为在这种情况下,T1
和T2
都需要包含H1
。