Reputation: 25
I am new to prolog and currently stuck trying to understand how to implement this. I need a predicate to find the second and the second last elements of a list using recursion, so for example:
second_secondLast([1,2], X, Y).
must return X=2, Y=1.
second_secondLast([1,2,3], X, Y).
must return X=2, Y=2.
second_secondLast([1], X, Y).
must print 'Error' and return false.
First, I have the error-checking clauses:
second_secondLast([], X, Y) :- print("Error"), !, fail.
second_secondLast([_], X, Y) :- print("Error"), !, fail.
Next, I tried something like this:
second_secondLast([Y,X],X,Y) :- !.
second_secondLast(L, X, Y) :-
second(L,X),
secondLast(L,Y).
second([_,S|_], X) :- X = S.
secondLast([P,_], Y) :- Y = P.
secondLast([F|R], Y) :- secondLast(R, Y).
However, the output using [1,2,3] is X=Y, Y=2.
I'm not sure if it is possible to force the output to be X=2
instead, or if there is a better method to do this.
Upvotes: 1
Views: 284
Reputation: 683
First of all, the output X=Y, Y=2.
has nothing to do with your program, it is an idiosyncracy of swipl (and maybe other interactive environments for Prolog implementations).
I think, your program looks fine, but you are asking for possible improvements.
second([_,S|_], S).
is a more elegant version of your second([_,S|_], X) :- X = S.
.
Likewise, secondLast([P,_], P).
is more elegant than your secondLast([P,_], Y) :- Y = P.
.
I would also prefer secondLast([_|R], Y) :- secondLast(R, Y).
to your
secondLast([F|R], Y) :- secondLast(R, Y).
.
Your error-checking clauses look fine to me.
You could also get rid of the predicate second
and alter the definition of second_secondLast
by using
second_secondLast([H,X|T], X, Y):-
secondLast([H,X|T], Y).
instead of your
second_secondLast(L, X, Y) :-
second(L,X),
secondLast(L,Y).
That change would also make it a bit more efficient. Another possibility is to use
second_secondLast(L, X, Y):-
L= [_,X|_],
secondLast(L, Y).
Then you could also get rid of the predicate secondLast
and alter the above clause to
second_secondLast(L, X, Y):-
L= [_,X|_],
append(_, [Y,_], L).
.
There is always a ton of possibilities...
Upvotes: 1