List 使用列表谓词在Prolog中查找交集
我对Prolog真的很陌生,我正在尝试制作一个List 使用列表谓词在Prolog中查找交集,list,prolog,intersection,List,Prolog,Intersection,我对Prolog真的很陌生,我正在尝试制作一个isIntersection,它给出两个列表的交集,并将答案放在第三个列表中。我不能使用任何Prolog列表谓词,因为它是用于类的,而这只是规则。这就是我所拥有的,我在调试和了解这个实现为什么是错误的方面遇到了困难。有人有什么想法吗 /* Checks if the item is in the list */ in(Item, [Item|Rest]). in(Item, [Not|Rest]) :- in(Item, Rest). /* Mak
isIntersection
,它给出两个列表的交集,并将答案放在第三个列表中。我不能使用任何Prolog列表谓词,因为它是用于类的,而这只是规则。这就是我所拥有的,我在调试和了解这个实现为什么是错误的方面遇到了困难。有人有什么想法吗
/* Checks if the item is in the list */
in(Item, [Item|Rest]).
in(Item, [Not|Rest]) :- in(Item, Rest).
/* Makes the intersection list */
isIntersection([], [], []).
isIntersection([H|R], List, [H|Final]) :-
in(H, List),
isIntersection(R, List, Final),
write(H).
isIntersection([Discard|Rest], List, Final) :-
isIntersection(Rest, List, Final),
write(Discard).
只有一个
列表
可以匹配基本情况,而这个简单的事实
抑制了整个计算。Prolog是一种非常通用的查询语言,所以让我们使用Prolog来查找问题
?- isIntersection([a,b],[c,b],Zs).
false.
这次失败不是我们所期望的。为了更好地定位问题,我们可以a)概括查询或b)减少输入大小。我将首先尝试概括一下:
?- isIntersection([a,b],Ys,Zs).
ERROR: Out of global stack
看起来我们运气不好,但是这个查询必须为Ys
生成无限多个列表,所以可以循环
我可以继续这样做,但为什么不让Prolog替我思考呢?我将尝试所有可能的列表:
?- length(L,_),append(Xs,Ys,L), isIntersection(Xs,Ys,Zs).
L = Xs, Xs = Ys, Ys = Zs, Zs = [] ;
L = Xs, Xs = [_G682],
Ys = Zs, Zs = [] ;
L = Xs, Xs = [_G682, _G685],
Ys = Zs, Zs = [] ;
L = Xs, Xs = [_G682, _G685, _G688],
Ys = Zs, Zs = [] ;
L = Xs, Xs = [_G682, _G685, _G688, _G691],
Ys = Zs, Zs = [] ...
因此,对于每个列表长度(到目前为止),只有一个解决方案是Ys
和Zs
为空列表。。。Ys
变大有什么解决方案吗
?- length(L,_),Ys = [_|_], append(Xs,Ys,L), isIntersection(Xs,Ys,Zs).
LOOPS
因此,让我们以上面的最小缺失示例为例,Ys
有一个元素:
?- isIntersection([],[a],[]).
false.
有了这个目标,现在看看你的代码
但还有另一个问题(在解决上述问题后):
规则将丢弃任何元素!但它应该只丢弃那些不在列表中的。因此:
isIntersection([Discard|Rest], List, Final) :-
list_without(List,Discard), % maplist(dif(Discard),List)
isIntersection(Rest, List, Final).
list_without([], _).
list_without([E|Es], F) :-
dif(E, F),
list_without(Es, F).
最后,始终关注负面例子。这里的许多尝试(错误地)成功地进行了查询,如isIntersection([a],[a],])
(您在/2中的关系最好称为/2中的元素_
)我会这样做,排序和合并以避免O(n2)性能:
intersection_of( Xs , Ys , Zs ) :- % to find the intersection of two sets, we
sort(Xs,X1) , % - sort the left source list, removing duplicates to ensure that it's a set
sort(Ys,Y1) , % - sort the right source list, removing duplicates to ensure that it's a set
merge(Xs,Ys,Z1) , % - merge them to find the common members (an ordered set)
( var(Zs) -> % - if the result is unbound,
Zs = Z1 ; % - simply unify the merge result with the result set
sort(Zs,Z1) % - otherwise, sort the result and match against the merge result
) . %
合并很简单
merge( [] , [] , [] ) .
merge( [_|_] , [] , [] ) .
merge( [] , [_|_] , [] ) .
merge( [X|Xs] , [Y|Ys] , [Z|Zs] ) :- X = Y , merge( Xs , Ys , Zs ) .
merge( [X|Xs] , [Y|Ys] , Zs ) :- X @< Y , merge( Xs , [Y|Ys] , Zs ) .
merge( [X|Xs] , [Y|Ys] , Zs ) :- X @> Y , merge([X|Xs] , Ys , Zs ) .
merge([]、[]、[])。
合并([124; 124;,],[])。
合并([],[124; 124;],])。
合并([X|Xs],[Y|Ys],[Z|Zs]):-X=Y,合并(Xs,Ys,Zs)。
合并([X|Xs],[Y|Ys],Zs):-X@Y,合并([X|Xs],Ys,Zs)。
@williness:突出显示不一致,因此令人恼火。单个字母变量的颜色不同,
中的以不同方式突出显示。简而言之:那根本没有帮助@false我通常更喜欢它,尽管前后不一致,因为注释变得更暗,代码中也有一些令人愉快的颜色。@Willenss:也许我们可以说服他们改变?那这就需要很多律师了。另外,对于使用的精确语法也有点争议。@false对于“元社区”的此类请求,通常的回答是“自己编程”(我想我曾经得到过这样的结果,所以我不想再尝试了:):)-我不知道从哪里开始,自己动手)。我怀疑lang prolog
规范不存在,并且匹配并使用了lang python
或lang perl
。@WillNess:您知道MSO和MSE的划分吗?似乎你只在旧的MSO上发布,现在是MSE。新的MSO不再显示total rep。只显示您的SO rep。因此,否决票似乎没有效果。转到->。
merge( [] , [] , [] ) .
merge( [_|_] , [] , [] ) .
merge( [] , [_|_] , [] ) .
merge( [X|Xs] , [Y|Ys] , [Z|Zs] ) :- X = Y , merge( Xs , Ys , Zs ) .
merge( [X|Xs] , [Y|Ys] , Zs ) :- X @< Y , merge( Xs , [Y|Ys] , Zs ) .
merge( [X|Xs] , [Y|Ys] , Zs ) :- X @> Y , merge([X|Xs] , Ys , Zs ) .