Newera
Newera

Reputation: 65

Prolog - Return a list with specific elements?

I am trying to learn Prolog and I've been doing some exercises.

There is a list with student's names. Write the predicate filter(L,LN) that returns a second list named LN which includes the names like this:

?- filter([kostas, dimitris, anna, antonis, antonia], LN).
LN = [kostas, anna, antonia]

So..it shows one and then skips one and does this continuously. This is what I've done but it isn't correct.

filter([],[]).
filter([H|T],[H|LN]) :-
    filter(T,LN,0).

filter([H|T],[H|LN],C) :-
    0 is C mod 2, 
    append(H,LN),
    C = C + 1, 
    filter(T,LN,C). 
filter([H|T],LN,C) :-
    (C/2) \= 0,
    C = C + 1,
    filter(T,LN,C).

Upvotes: 4

Views: 2462

Answers (3)

CapelliC
CapelliC

Reputation: 60024

I don't dislike merging arithmetic and list processing:

filter(Xs, Ys) :- must_be(list, Xs), findall(Y, (nth1(I,Xs,Y), I mod 2 =:= 1), Ys).

@Fatalize answer in DCG flavour:

filter_dcg(Xs, Ys) :- must_be(list, Xs), phrase(keep_1(Ys), Xs).

keep_1([]) --> [].
keep_1([A]) --> [A].
keep_1([A|As]) --> [A,_], keep_1(As).

Upvotes: 1

user1812457
user1812457

Reputation:

One of the many cases when using a DCG makes your life much easier:

s([]) --> [].
s([X|Xs]) --> [X], t(Xs).

t([]) --> [].
t(Xs) --> [_], s(Xs).

filter_dcg(List, Filtered) :-
    phrase(s(Filtered), List).

Without a DCG, this would look something like:

q([], []).
q([X|Xs], [X|Ys]) :-
    r(Xs, Ys).

r([], []).
r([_|Xs], Ys) :-
    q(Xs, Ys).

filter_pred(List, Filtered) :-
    q(List, Filtered).

The take home message here is that what you are trying to achieve is easily implemented as a state machine with two states. Each of them transitions to the other, one keeps its input and the other one throws it away.

Upvotes: 4

Fatalize
Fatalize

Reputation: 3543

Here is a simple answer that doesn't use any arithmetic:

filter([],[]).
filter([A],[A]).
filter([A,_|T],[A|T2]) :-
    filter(T,T2).

For an empty list, the result is an empty list. For a list of one element, the result is a list of that element. For a list of two ore more elements, the result is the first element followed by the result of the filtering on elements after the first two (so we discard the second one).

Upvotes: 2

Related Questions