Given a list eg [1,2,3,7,2,5,8,9,3,4]
how would I extract the sequences within the list?
A sequence is defined as an ordered list (Normally I would say n-tuple but I have been told in prolog a tuple is referred to as a sequence). So we want to cut the list at the point where the next element is smaller than the previous one.
So for the list [1,2,3,7,2,5,8,9,3,4]
it should return:
[ [1,2,3,7], [2,5,8,9], [3,4] ]
%ie we have cut the list at position 4 & 8.
For this exercise you CANNOT use the construct ;
or ->
Many thanks in advance!
EXAMPLE RESULTS:
eg1.
?-function([1,2,3,7,2,5,8,9,3,4],X): %so we cut the list at position 4 & 9
X = [ [1,2,3,7], [2,5,8,9], [3,4] ]
.
eg2.
?-function([1,2,3,2,2,3,4,3],X): %so we cut the list at position 3,4 & 8
X = [ [1,2,3], [2], [2,3,4], [3] ].
Hopefully that helps clarify the problem. If you need further clarification just let me know! Thanks again in advance for any help you are able to provide.
First, let's break it down conceptually. The predicate
list_ascending_rest/3
defines a relation between a listXs
, the left-most ascending sublist of maximum lengthYs
, and the remaining itemsRest
. We will use it like in the following query:The straight-forward predicate definition goes like this:
Then, let's implement predicate
list_ascendingParts/2
. This predicate repeatedly useslist_ascending_rest/3
for each part until nothing is left.Example queries:
Edit 2015/04/05
What if the ascending parts are known but the list is unknown? Let's find out:
And let's not forget about the most general query using
list_ascendingParts/2
:Edit 2015-04-27
Room for improvement? Yes, definitely!
By using the meta-predicate
splitlistIfAdj/3
one can "succeed deterministically" and "use non-determinism when required", depending on the situation.splitlistIfAdj/3
is based onif_/3
as proposed by @false in this answer. So the predicate passed to it has to obey the same convention as(=)/3
andmemberd_truth/3
.So let's define
(#>)/3
and(#>=)/3
:Let's re-ask above queries, using
splitlistIfAdj(#>=)
instead oflist_ascendingParts
:Last, the most general query. I wonder what the answers look like:
maplist/3
as suggested in the comment won't help you here becausemaplist/3
is good at taking a list and mapping each element into a same-size collection of something else, or establishing a relation evenly across all of the individual elements. In this problem, you are trying to gather contiguous sublists that have certain properties.Here's a DCG solution. The idea here is to examine the list as a series of increasing sequences where, at the boundary between them, the last element of the prior sequence is less than or equal to the first element of the following sequence (as the problem statement basically indicates).
The only reason for the rule
sequences([]) --> [].
is if you wantpartition([], [])
to be true. Otherwise, the rule isn't required.