0
votes

I have to make a predicate reverseeven(List, Reversed), that will reverse a list ONLY if the list has an even number of elements, and will return the empty list if it does not. I have a function that determines whether the list has an even number of elements and a reverse function:

evenlength([_,_]).
evenlength([_,_|X]):-
    evenlength(X).

reverse([_,_],R).
reverse([H|T], R):-
    reverse(T,ReverseT), append(ReverseT, [H], R).

But I'm unsure of how to combine the two.

1

1 Answers

0
votes

You can't "combine" predicates, but you can have a logical conjunction between two (or more) predicates which will succeed only if both of them succeed:

reverseEven(List, Reversed) :- 
      evenlength(List),            % This must succeed 
      reverse(List, Reversed).     % and this one in order this case to succeed

reverseEven(_, []).                % this will succeed otherwise

The above is not the most efficient implementation (you can utilize the cut ! operator after the check for the even length for example). But it shows the idea.

Update By the way, your reverse predicate should look like this:

reverse([],[]).    % Empty list is a reverse of empty list
reverse([H|T], R):-
    reverse(T,ReverseT), append(ReverseT, [H], R).    

Update 2 Thanks @Lurker. The above code will produce two answers. The first one will be correct. If we ask Prolog to search further it will find another answer which is empty list, as the second clause is always true. In order to solve this, we can explicitly check that the length of the list is not even using the negation operator, or what I find more elegant is just to add another clause for the empty list, and for the non-even checking just use the existing evenlength with the list with extra element:

reverseEven([], []).  
reverseEven(List, Reversed) :- 
    evenlength(List),            % This must succeed 
    reverse(List, Reversed).     % and this one in order this case to succeed

reverseEven([H|T], []) :- 
    evenlength([H|[H|T]]).