Search code examples
prolog

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


I have a task to remove all elements which have the same value as the index from the list. I have this code but it does not work.

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).

The main mistakes were in syntax. Also conditions has to be swiped. Now it changed and program works.

SOLUTION:


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).

Solution

  • In addition to the modifications already pointed out by Gusbro, you also need to invert the conditions used to include/exclude elements from the input list:

    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).
    

    Examples:

    %  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.
    

    To avoid spurious choice point:

    • Use a wrapper predicate to maintain the arguments in the original desired order.
    • In the helper predicate, change the order of the first two arguments, to take advantage of Prolog's first argument indexing.
    • Use -> to avoid the need to evaluate a deterministic condition and also its negation.

    Thus, an improved version of this predicate is as follows:

    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).
    

    Examples:

    ?- 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].