Prolog:从列表B中删除列表A中出现的所有元素

时间:2017-03-15 20:14:21

标签: list prolog predicate

我试图定义一个谓词"删除(L1,L2,L3)"当L3等于L2减去L1中包含的任何这些元素时,这是有效的。例如。删除([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。我无法告诉我的谓词无法正常工作的案例,因为它已经被学校系统测试过,而系统并没有告诉我哪些测试用例失败了。

1 个答案:

答案 0 :(得分:3)

非常接近

剩下的一个问题是,您正在对不承认此类阅读的谓词应用完美合理的逻辑推理。如果您只是简单地应用以下非常直接的更改,那么您的代码将完全按预期工作:

  1. 而不是(\=)/2,请使用dif/2
  2. 而不是\+(isNonElement(X, Y)),只需写下:member(X, Y)
  3. 第一个更改始终是可取的:它通常会使您的程序在更多方向上可用。第二个改变是通过使用纯谓词来避免使用不纯的否定。

    总的来说,我们现在有:

    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。这是最直接的关系之一。但是,请注意IEntityService<T>非常有名:命令式总是暗示一个特定的使用方向,但我们在这里考虑的关系也承认了许多其他使用模式!