Search code examples
prolog

Prolog list exercise


Here is my exercise: define a predicate in prolog which, applied to a list L of integers, gives as a result the list of the successors of the even elements present in L.

The code i wrote work only if one element is even , can someone help me figure out where I'm wrong?

even(X):- 0 is mod(X,2).
odd(X):- 1 is mod(X,2).

list_even([],[]).    
list_even([T|C],K):- even(T), E is T+1, list_even(C,K1), append(K1,E,X), K is X.
list_even([T|C],K):- odd(T),list_even(C,K).


Solution

  • Some flaws in your code are:

    • append(K1, E, X): This goal should append two lists to generate a third list; however, E is just an element, not a list. So you need to write append(K1, [E], X).
    • K is X: This goal evaluates the arithmetic expression represented by the variable X and unifies its value with variable K; however, X is a list, not an arithmetic expression. So you need to remove it.

    So the correct code would be as follows:

    list_even([], []).
    list_even([T|C], K):- even(T), E is T+1, list_even(C, K1), append(K1, [E], K).
    list_even([T|C], K):- odd(T), list_even(C, K).
    

    Example:

    ?- list_even([1, 20, 3, 40, 5, 7, 8], Successors).
    Successors = [9, 41, 21] ;
    false.
    

    Note that in the obtained answer, the successors appear in reverse order (the first even element in the input list is 20, but its successor 21 is the last element in the output list).

    So a better code is as follows:

    even_number_successors([], []).
    even_number_successors([X|Xs], Successors) :-
       (   X mod 2 =:= 0
       ->  Y is X + 1,
           Successors = [Y|Ys]
       ;   Successors = Ys ),
       even_number_successors(Xs, Ys).
    

    Example:

    ?- even_number_successors([1, 20, 3, 40, 5, 7, 8], Successors).
    Successors = [21, 41, 9].