Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 使用列表谓词在Prolog中查找交集_List_Prolog_Intersection - Fatal编程技术网

List 使用列表谓词在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

我对Prolog真的很陌生,我正在尝试制作一个
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 ) .