2017-03-15 126 views
2

我试图定义一个谓词“删除(L1,L2,L3)”,当L3等于L2减去这些元素中包含的任何元素L1。例如。删除([1],[1,2,3],X)=>会统一为X = [2,3]。我的代码如下:序言:从列表B中删除列表A中发生的所有元素

isNonElement(_, []). 
isNonElement(X, [Y|Z]) :- X \= Y, isNonElement(X,Z). 

delete(_, [], []). 
delete(Y, [X|W], Z) :- \+(isNonElement(X, Y)), delete(Y, W, Z). 
delete(Y, [X|W], [X|Z]) :- isNonElement(X, Y), delete(Y, W, Z). 

但是它似乎不适用于每个测试用例。任何人都可以帮我解决我的代码有什么问题吗?

在此先感谢!

此致敬礼, Skyfe。

P.S.我不能告诉我的谓词不能正确工作的情况,因为它是由学校系统测试的,它不告诉我哪个测试用例失败。

+0

*减去任何*或减*所有*。你的例子只有一个元素,所以这是在一般情况下告诉你的后果。另外*不要*使用'delete'作为谓词名称。它已经被图书馆谓词所采用。使用更具体的东西。 – lurker

回答

3

你是非常接近

剩下的一个问题是,你正在应用一个完全合理的逻辑推理来判断不承认这样的阅读。你的代码工作完全按照预期的,如果你简单地套用以下的极其直接的变化:中

  1. 代替(\=)/2,使用dif/2
  2. 代替\+(isNonElement(X, Y)),简单地写:member(X, Y)

第一次更改总是可取的:它通常会使您的程序在更多方向上可用。第二个改变通过使用纯谓词来避免使用不纯否定。

总体而言,我们现在有:

 
isNonElement(_, []). 
isNonElement(X, [Y|Z]) :- dif(X, Y), isNonElement(X,Z). 

delete(_, [], []). 
delete(Y, [X|W], Z)  :- member(X, Y), delete(Y, W, Z). 
delete(Y, [X|W], [X|Z]) :- isNonElement(X, Y), delete(Y, W, Z). 

现在检查了这一点:首先,你的测试案例:

 
?- delete([1], [1,2,3], X). 
X = [2, 3] ; 
false. 

按预期工作!

其次,具有可变的情况下,为L2

 
?- delete([], L2, []). 
L2 = [] ; 
false. 

这似乎也是很不错的。

三,另一个变量:

 
?- delete([X], [1,2,3], Ls3). 
X = 1, 
Ls3 = [2, 3] ; 
X = 2, 
Ls3 = [1, 3] ; 
X = 3, 
Ls3 = [1, 2] ; 
Ls3 = [1, 2, 3], 
dif(X, 3), 
dif(X, 2), 
dif(X, 1) ; 
false. 

注意现在X不同的可能性,并dif/2如何在回答用于表达X必须从某个整数不同在这种情况下, 。

使用不纯谓词排除这样更通用的用法,并且您的评分系统也可以尝试这样的情况。

请注意,您当然可以轻松地自己实现member/2。这是最直接的关系之一。然而,还要注意delete/3是可怕的命名:一个势在必行总是意味着使用一个特定的方向,但我们正在考虑在这里的关系也承认许多其他用途 模式!

+0

感谢您的详细解答!替换isNonElement的否定由会员修正。我不允许使用预定义的谓词,所以我只是重写它。至于谓词的名称,这是我的课程老师的选择,我不能改变它,但我同意。再次感谢你的帮忙:) – Skyfe

+2

太好了!请注意,初始溶液已经使用预定义的谓词'(\ +)/ 1'和'(\ =)/ 1',因此采取与一粒盐这样的要求。要查看版本之间的一些差异,请考虑以下查询:'? - delete([X],[a],Z)'。在初始版本中,如果*'X'为'a',则会得到'Z = []'正确的*,但是否则错误!如果使用'构件/ 2'代替不合理的否定,则得到:'X = A,Z = []',它是至少一个*正确*溶液。然而,这是不完整* *,这是因为其他的解决方案是'Z = [A],DIF(X,一)'。只有'dif/2'给你这个! – mat