Prolog 从列表中删除与索引具有相同值的元素

Prolog remove elements which have the same value as the index from the list

我的任务是从列表中删除与索引具有相同值的所有元素。我有这个代码,但它不起作用。

remove(_, [], []).
remove(position, [H | T1], [H | T2]) :-
    H =:= position,
    next_position = position + 1,
    remove(next_position, T1, T2).
    
remove(position, [H | T1], T2) :-
    H =\= position,
    next_position = position + 1,
    remove(next_position, T1, T2).

:-remove(1,[1, 2, 2, 3, 4, 5, 6, 7, 8],Res),
    write(Res).

主要错误在句法上。还必须刷条件。现在它改变了,程序可以工作了。

解决方案:


remove(_, [], []).
remove(Position, [H | T1], [H | T2]) :-
    H =\= Position,
    NextPosition is Position + 1,
    remove(NextPosition, T1, T2).
    
remove(Position, [H | T1], T2) :-
    H =:= Position,
    NextPosition is Position + 1,
    remove(NextPosition, T1, T2).

:-remove(1,[1, 2, 2, 3, 4, 5, 6, 7, 8],Res),
    write(Res).

除了 Gusbro 已经指出的修改之外,您还需要反转用于输入列表中 include/exclude 个元素的条件:

remove(_, [], []).

remove(Position, [H|T1], [H|T2]) :-
    H =\= Position,                % include element if it is different from its index
    Next_position is Position + 1,
    remove(Next_position, T1, T2).

remove(Position, [H|T1], T2) :-
    H =:= Position,                % exclude element if it is equal to its index
    Next_position is Position + 1,
    remove(Next_position, T1, T2).

示例:

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

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

%  index      1 2 3 4 5 6 7 8 9
?- remove(1, [1,2,2,3,4,5,6,7,8], Res).
Res = [2, 3, 4, 5, 6, 7, 8] ;
false.

避免虚假选择点:

  • 使用 wrapper 谓词以原始所需的顺序维护参数。
  • helper 谓词中,更改前两个参数的顺序,以利用 Prolog 的第一个参数索引。
  • 使用 -> 来避免评估确定性条件及其否定的需要。

因此,该谓词的改进版本如下:

improved_remove(Start, List, NewList) :-
    remove_loop(List, Start, NewList).

remove_loop([], _, []).

remove_loop([H|T1], Position, L) :-
    (   H =\= Position
    ->  L = [H|T2]
    ;   L = T2 ),
    Next_position is Position + 1,
    remove_loop(T1, Next_position, T2).

示例:

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

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

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