I have a prolog assignment.
I need to look at the first item in a list, see if its following items are the same until they are not and separate the lists by the first item and its duplicates. e.g if my list was a,a,a,b,c it would separate it into first: a,a,a. second: b,c.
My current solution works except that the final matching item comes into the second list, not the first. I can't seem to think of a way to get it to appear in the first list instead.
grab([],[],[]).
grab([A,A|L],[A|L2],Rest) :- grab([A|L],L2,Rest).
grab([A|L],Init,[A|L2]) :- grab(L,Init,L2).
Here is another solution that takes into account what @Sarah wrote. Given this use,
grab/3
should never succeed for an empty list for the first or second argument.In the definition you gave, you get many different answers:
When the first two elements are different you do not need a recursive goal.
Here is a solution using dcgs. Most interesting is here the usage of a non-terminal that is not context-free. I will start with an attempt that is too general:
grab_tentative/3
ensures thatXs
consists ofYs
concatenated withZs
. That is way too general, but all intended solutions are already included.The first answer says that
Ys = []
, but (as has been clarified by @Sarah),Ys
should always be a non-empty list, so we can restrict the answers to non-empty lists:The answers
Xs = [A, B, C], Ys = [A, B], Zs = [C]
andXs = Ys, Ys = [A, B, C], Zs = []
both permit thatA
andB
are different. So we have to add that they are the same:Now, the answers are already a bit better:
The first answer includes that
A = B
. So, it really should containdif(A,B)
. To do so we need to introduce such a context. Here is way to do this. Note thator_end//1
is like[]//0
, except that it ensures some extra condition.Now, the answers are as expected: