Prolog将元素删除到给定列表中

时间:2017-05-09 15:59:07

标签: prolog

您好我希望对此任务提出一些建议或意见:

定义一个带有三个参数的语句,其中第一个是列表,第二个是元素(原子或列表),最后一个是必须完成它的列表等于第一个但是第一个列表'元素匹配第二个参数,已经不见了。

Examples:

> elimina([f, e, d, [a, h], a, d, a], a, L)

L = [f, e, d, [a, h], d]

> elimina([f, e, d, [ a, h], a, [d, a]], [a, h], L)

L = [f, e, d, a, [d, a]]

我试过了:

elimina([],_,[]).
elimina([X],X,[]).
elimina([X],Y,[X]).
elimina([H|T],H,Result) :-
 elimina([T],H,Result).
elimina([H|T],Y,Result):-
 elimina([T],H,Result).

当我喊出递归调用时,我怀疑要写什么:

elimina([T],H,Result).

因为首先我不知道输入第二个元素与头部匹配时的行为有多么不同,而不是与头部匹配;所以我打了同样的电话。 我也怀疑是因为:确实需要提出基本案例:elimina([X],Y,[X]).?我认为我们可以通过将要删除的元素与真正进入列表的元素进行匹配来传递练习。

感谢您的时间。

2 个答案:

答案 0 :(得分:6)

有一种非常通用的方法可以在Prolog中测试自己的代码。只需要让Prolog通过最常见的问题生成所有可能性。

| ?- elimina([], D, Ys).
     Ys = [].            % 1: nice!

| ?- elimina([X], D, Ys).
     D = X,              % 1: nice!
     Ys = []
  ;  Ys = [X]            % 2: lacks dif(X, D)
  ;  X = [],             % 3: correct but subsumed by 1
     D = [],
     Ys = []
  ;  D = X,              % 4: incorrect
     Ys = [[]]
  ;  X = [],             % 5: correct but subsumed by 1
     D = [],
     Ys = []
  ;  X = [],             % 6: incorrect
     D = [],
     Ys = [[]]
  ;  X = [],             % 7: correct but subsumed by 1
     D = [],
     Ys = []
  ;  ...

对于空列表,一切都很好。但对于单元素列表,有许多多余的答案!实际上,应该只有两个答案:

    D = X, Ys = []
;   dif(D, X), Ys = [X].

所以现在选择一些你想改进的案例!

也许回答#4并设置D = a,X = a:

| ?- elimina([a], a, Ys).
     Ys = []        % 1: nice
  ;  Ys = [a]       % 2: incorrect
  ;  Ys = [[]]      % 3: incorrect
  ;  Ys = []        % 4: correct but subsumed by 1
  ;  Ys = [[]]      % 5: incorrect and subsumed by 3
  ;  Ys = []        % 6: correct but subsumed by 1
  ;  ...

所以我会选择实际上应该失败的#3,但不会

| ?- elimina([a],a,[[]]).
     true
  ;  true
  ;  ...

通过插入 false 和一些额外的公式来缩小罪魁祸首:

| ?- elimina([a],a,[[]]).
     false.

elimina([],_,[]) :- false.
elimina([X],X,[]) :- false.
elimina([X],Y,[X]) :- Y = a, X = [].
elimina([H|T],H,Result) :- false,
   elimina([T],H,Result).
elimina([H|T],Y,Result):- Result =  [[]],
   elimina([T],H,Result).

现在看看剩下的东西并考虑一下。这些剩余规则是否真的存在?

在剩余的可见部分中一定有错误!

答案 1 :(得分:4)

在描述列表时,通常值得考虑将DCG用于任务。你可以这样描述这样的关系:

elimina(L1,X,L2) :-              % L2 is described by
   phrase(elimina_x(L1,X),L2).   % elimina_x//2

elimina_x([],_X) -->             % nothing to delete
   [].                           % from the empty list
elimina_x([X|Xs],X)  -->         % if the head of the list equals X
   elimina_x(Xs,X).              % it's not in the list, same for the tail
elimina_x([X|Xs],Y)  -->         % if the head of the list
   {dif(X,Y)},                   % differs from Y
   [X],                          % it is in the list
   elimina_x(Xs,Y).              % same for the tail

您的示例查询会产生所需的结果。

   ?- elimina([f, e, d, [a, h], a, d, a], a, L).
L = [f,e,d,[a,h],d] ? ;
no
   ?- elimina([f, e, d, [ a, h], a, [d, a]], [a, h], L).
L = [f,e,d,a,[d,a]] ? ;
no

或者,您也可以使用if_/3(=)/3tfilter/3更紧凑地表达此关系:

dif_t(X,Y,T) :-
   if_(X=Y,T=false,T=true).

elimina(L1,X,L2) :-
   tfilter(dif_t(X),L1,L2).

上述查询与此版本的答案相同。