Your program combines many different issues into one predicate. Let's try to separate those a bit. Also, I assume you are searching for a maximal sublist of two or more elements containing identical elements.
Let's start with an approximation of what you want: Identifying sublists. Don't worry that this is way too broad, we will refine it later on. I will use DCGs for this purpose. The non-terminal seq//1
describes an arbitrary sequence.
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
This is an extremely useful non-terminal!
?- phrase((seq(Prefix),seq(Sublist),seq(Postfix)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)]).
Prefix = Sublist, Sublist = [],
Postfix = [a,a,b,2,2,2,a+1,a+1,s(1,2)]
; Prefix = [], Sublist = "a",
Postfix = [a,b,2,2,2,a+1,a+1,s(1,2)]
; ... .
Both answers are not expected, we only want sublists of length 2 or more, so we have to restrict that definition a bit. Say, by demanding that Sublist
should contain at least two elements. That is Sublist = [_,_|_]
.
?- Sublist = [_,_|_],
phrase((seq(Prefix),seq(Sublist),seq(Postfix)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)]).
Sublist = "aa", Prefix = [],
Postfix = [b,2,2,2,a+1,a+1,s(1,2)]
; Sublist = "aab", Prefix = [],
Postfix = [2,2,2,a+1,a+1,s(1,2)]
; ... .
The first answer shows a sublist we are searching for. But the second is still incorrect: All elements of the sublist should be equal. The easiest way is to use maplist/2
:
?- maplist(=(_),Es).
Es = []
; Es = [_A]
; Es = [_A,_B]
; Es = [_A,_B,_C]
; ... .
There are several places where we could state that requirement. I will put it at the earliest place possible:
?- Sublist = [_,_|_],
phrase(( seq(Prefix),
seq(Sublist),{maplist(=(_),Sublist)},
seq(Postfix)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)]).
Sublist = "aa", Prefix = [], Postfix = [b,2,2,2,a+1,a+1,s(1,2)]
; Sublist = [2,2], Prefix = "aab", Postfix = [2,a+1,a+1,s(1,2)]
; Sublist = [2,2,2], Prefix = "aab", Postfix = [a+1,a+1,s(1,2)]
; Sublist = [2,2], Prefix = [a,a,b,2],
Postfix = [a+1,a+1,s(1,2)]
; Sublist = [a+1,a+1], Prefix = [a,a,b,2,2,2],
Postfix = [s(1,2)]
; false.
So now, all sublists contain identical elements. Alas, we get both [2,2]
and [2,2,2]
as sublist. We only want the maximal sublist. So how can we describe what a maximal sublist is?
One way is to look in front of our sublist: There must not be the very same element of our sublist. Thus, either there is nothing (epsilon) in front, or a sequence which ends with an element different to ours.
difel(_E,[]).
difel(E, Es) :- dif(E,F), phrase((seq(_), [F]), Es).
?- Sublist = [_,_|_],
phrase(( seq(Prefix),{difel(E,Prefix)},
seq(Sublist),{maplist(=(E),Sublist)},
seq(Postfix)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)]).
Sublist = "aa", Prefix = [], E = a, Postfix = [b,2,2,2,a+1,a+1,s(1,2)]
; Sublist = [2,2], Prefix = "aab", E = 2, Postfix = [2,a+1,a+1,s(1,2)]
; Sublist = [2,2,2], Prefix = "aab", E = 2, Postfix = [a+1,a+1,s(1,2)]
; Sublist = [a+1,a+1], Prefix = [a,a,b,2,2,2], E = a+1, Postfix = [s(1,2)]
; false.
One incorrect answer less. There is still one lurking around at the end.
?- Sublist = [_,_|_],
phrase(( seq(Prefix),{difel(E,Prefix)},
seq(Sublist),{maplist(=(E),Sublist)},
( [] | [F],{dif(E,F)},seq(_) ) ),
[a,a,b,2,2,2,a+1,a+1,s(1,2)]).
Sublist = "aa", Prefix = [], E = a, F = b
; Sublist = [2,2,2], Prefix = "aab", E = 2, F = a+1
; Sublist = [a+1,a+1], Prefix = [a,a,b,2,2,2], E = a+1, F = s(1,2)
; false.
That is not exactly what you wanted: You simply wanted the lengths. For this, add length([_|Prefix],I), length(Sublist,Len)
.
So here is the final definition:
plateau(Xs, I, Len) :-
Sublist = [_,_|_],
phrase(( seq(Prefix),{difel(E,Prefix)},
seq(Sublist),{maplist(=(E),Sublist)},
( [] | [F],{dif(E,F)},seq(_) ) ),
Xs),
length([_|Prefix],I),
length(Sublist,Len).