Reputation: 55
How do i write a goal that deletes the last three elements from a list L producing another list L1?
Also, how would I write multiple goals to delete the first three elements and the last three elements from a list L producing L2?
Upvotes: 3
Views: 6236
Reputation: 60034
Prolog it's a bit different from other languages, but it also has a libray (standard ISO) that's worth to learn:
delete_last_3(L, L1) :-
append(L1, [_,_,_], L).
Now the other request come easy:
delete_first_and_last_3(L, L2) :-
append([_,_,_], LT, L), delete_last_3(LT, L2).
Test:
?- delete_last_3([1,2,3,4,5,6,7],X).
X = [1, 2, 3, 4] .
?- delete_first_and_last_3([1,2,3,4,5,6,7,8,9],L).
L = [4, 5, 6] .
Upvotes: 5
Reputation: 22585
You might want to try something like this:
without_last_three([_,_,_], []).
without_last_three([Head|Tail], [Head|NTail]):-
without_last_three(Tail, NTail).
without_three_sides([_,_,_|L], L2):-
without_last_three(L, L2).
The first predicate will return a list without the last three elements, and fail in case there are less than three elements.
The second predicate will return a list without the first and last three elements, and fail in case there are less than six elements.
Upvotes: 3
Reputation: 1312
Step one of logic programming, start with the base cases. What do you want to happen when there are fewer than three elements? I guess you want an empty list?
without_last_three([], []).
without_last_three([_], []).
without_last_three([_,_], []).
without_last_three([_,_,_], []).
Now, for a list with more than three elements, you want to keep the first element, and remove three from the remaining elements. You might first try to write:
without_last_three([A|L], [A|M]) :- without_last_three(L, M). !!wrong
but this will cause incorrect results due to back-tracking. The simplest way to fix that is to verify that L has more than three elements:
without_last_three([A,B,C,D|L], [A|M]) :- without_last_three([B,C,D|L], M).
But a more elegant solution would be to use Prolog's cut operator:
without_last_three([A|L], [A|M]) :- !, without_last_three(L, M).
To implement without_first_three, without getting bored, you could simply reverse the list, remove the last three, and flip it back again:
without_first_three(I, O) :- reverse(I, A), without_last_three(A, B), reverse(B, O).
or you could just write down some really simple rules:
without_first_three([], []).
without_first_three([_], []).
without_first_three([_,_], []).
without_first_three([_,_,_|L], L).
(Thinking about it, maybe it would be nicer to implement without_last_three in terms of without_first_three, not the other way around)!
Upvotes: 0