Bob Smith
Bob Smith

Reputation: 55

Delete Last 3 elements of List L to make List L1 in Prolog

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

Answers (3)

CapelliC
CapelliC

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

gusbro
gusbro

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

Conrad Irwin
Conrad Irwin

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

Related Questions