Prolog:从列表 B 中删除列表 A 中出现的所有元素
Prolog: removing all elements that occur in list A from list B
我正在尝试定义一个谓词 "delete(L1, L2, L3)",它在 L3 等于 L2 减去 L1 中包含的任何这些元素时有效。例如。 delete([1], [1,2,3], X) => 将统一 X = [2,3]。我的代码如下:
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。我无法告诉我的谓词在哪些情况下不能正常工作,因为它是由一个学校系统测试的,它没有告诉我它失败了哪些测试用例。
你非常接近!
剩下的一个问题是,您正在对不允许这样阅读的谓词应用完全合理的逻辑推理。如果您简单地应用以下极其直接的更改,您的代码将完全按预期工作:
- 代替
(\=)/2
,使用dif/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
的命名非常糟糕: 命令式 总是暗示特定的使用方向,但我们在这里考虑的关系也承认许多其他使用模式!
我正在尝试定义一个谓词 "delete(L1, L2, L3)",它在 L3 等于 L2 减去 L1 中包含的任何这些元素时有效。例如。 delete([1], [1,2,3], X) => 将统一 X = [2,3]。我的代码如下:
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。我无法告诉我的谓词在哪些情况下不能正常工作,因为它是由一个学校系统测试的,它没有告诉我它失败了哪些测试用例。
你非常接近!
剩下的一个问题是,您正在对不允许这样阅读的谓词应用完全合理的逻辑推理。如果您简单地应用以下极其直接的更改,您的代码将完全按预期工作:
- 代替
(\=)/2
,使用dif/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
的命名非常糟糕: 命令式 总是暗示特定的使用方向,但我们在这里考虑的关系也承认许多其他使用模式!