序言。从第一个列表中删除在第二个列表中出现次数为偶数的项目

Prolog. Remove from the first list items that have an even number of occurrences in the second list

我刚开始学习如何在 prolog 中使用列表,我试图根据类似任务的示例编写一个程序,但它不起作用。 任务是 - 从第一个列表中删除在第二个列表中出现次数为偶数的项目。

我在这个函数中有这样的逻辑:

  1. 函数 counter 应该 return 列表中某个元素的数量。
  2. 函数remove忽略第二个列表中数量为偶数的元素

我的代码:

counter(_,[],0).

counter(Number, [H|T], Quantity):- 
    Number =:= H,
    UpdatedQuantity is Quantity + 1,
    counter(Number, T, UpdatedQuantity).
    
counter(Number, [H|T], Quantity):- 
    Number =\= H,
    counter(Number, T, Quantity).


remove([], [], []).

remove([H1|T1], T2, [H1 | T1]) :-
    counter(H1, T2, Quantity),
    Quantity mod 2 =:= 0,
    remove(T1, T2, T1).
    
remove([H1|T1], T2, T1) :-
    counter(H1, T2, Quantity),
    Quantity mod 2 =\= 0,
    remove(T1, T2, T1).

例如,移除([1,2,3,4][1,1,2,3,3,3,4,4,4,4,5,6,7,7], Res ) 将 return Res = [2,3,4,5,7,7]

修改谓词counter/3的第二个子句如下:

  • 首先找到一个更简单的问题实例的解决方案。
  • 然后使用该解决方案获得问题原始实例的解决方案。
counter(_, [], 0).

counter(Number, [H|T], UpdatedQuantity):-
    Number =:= H,
    counter(Number, T, Quantity),    
    UpdatedQuantity is Quantity + 1. 

counter(Number, [H|T], Quantity):-
    Number =\= H,
    counter(Number, T, Quantity).

修改谓词remove/3如下:

  • 将第一个子句替换为 remove([], _, []),因为第二个列表不需要为空即可停止递归。
  • 在最后两个子句中,将出现在第三个参数中的 T1 替换为 T3(新变量),因为结果列表可能不等于第一个输入列表。
  • 另外,交换最后两个子句中使用的条件;否则,您将删除出现次数 奇数 的项目。
remove([], _, []).

remove([H1|T1], T2, [H1|T3]) :-
    counter(H1, T2, Quantity),
    Quantity mod 2 =\= 0,
    remove(T1, T2, T3).

remove([H1|T1], T2, T3) :-
    counter(H1, T2, Quantity),
    Quantity mod 2 =:= 0,
    remove(T1, T2, T3).

示例:

?- remove([1,2,3,4,5],[1,1,2,2,2,4], Res).
Res = [2, 4] ;
false.

改进解决方案避免虚假选择点和counter/3的冗余调用。

improved_counter([], _, 0).
improved_counter([H|T], Number, UpdatedQuantity):-
    improved_counter(T, Number, Quantity),
    (   Number =:= H
    ->  UpdatedQuantity is Quantity + 1
    ;   UpdatedQuantity is Quantity ).

improved_remove([], _, []).
improved_remove([H1|T1], T2, Res) :-
    improved_counter(T2, H1, Quantity), % solve this goal only once!
    (   Quantity mod 2 =:= 0
    ->  Res = T3
    ;   Res = [H1|T3] ),
    improved_remove(T1, T2, T3).

示例:

?- improved_remove([1,2,3,4,5],[1,1,2,2,2,4], Res).
Res = [2, 4].