Prolog check if list X has any duplicates - prolog

I have the function already but it is not working exactly as I want it to. The function I have is below..
isSet(List) :-
\+ (
select(Element, List, Tail),
select(Element, Tail, _)
).
When I do isSet([1,2,3]) it gives me true which is expected. When I do isSet([1,1,2]) it gives me false which is also what I expect and is correct. My question is how can I pass a list that is already made? For example If I do X = [1,2,3] and than pass it as a argument like isSet(X) it should give me true but instead it generates an error.
What can I do to fix this?
Edit:
?- [db].
true.
?- X = [1,2,3].
X = [1, 2, 3].
?- isSet(X).
false.
?- X = (1,2,3).
X = (1, 2, 3).
?- isSet(X).
false.
?- X = [1,1,2].
X = [1, 1, 2].
?- isSet(X).
false.

SWI-Prolog allows the form $Xs to access a variable from a previous query. E.g.:
?- Xs=[1,2,3].
Xs = [1, 2, 3].
?- isSet($Xs).
Xs = [1, 2, 3].
?- isSet([1|$Xs]).
false.
BTW, it's slightly more efficient to write your code like this (and I suggest using Rest rather than Tail: the latter is typically used in the form List=[Head|Tail]):
isSet(List) :-
\+ ( select(Element, List, Rest),
member(Element, Rest)
).
Also, you can't write a list like this: X = (1,2,3) ... that's actually something different:
?- write_canonical((1,2,3)), nl.
','(1,','(2,3))
true.

As there are discussions on how to best define the concept of "sets represented by lists", I humbly submit the following:
real_actual_set([]).
real_actual_set([X | Xs]) :-
nonmember_of(X, Xs),
real_actual_set(Xs).
nonmember_of(_X, []).
nonmember_of(X, [Y | Ys]) :-
dif(X, Y),
nonmember_of(X, Ys).
This is pure and works properly even in the presence of variables, including the most general query, and any lists containing variables that we would try to bind later:
?- real_actual_set([1, 2, 3]).
true .
?- real_actual_set([1, 1, 2]).
false.
?- real_actual_set([A, B, C]).
dif(A, C),
dif(A, B),
dif(B, C).
?- real_actual_set([A, A, B]).
false.
?- real_actual_set(Set).
Set = [] ;
Set = [_2222] ;
Set = [_2672, _2678],
dif(_2672, _2678) ;
Set = [_2970, _2976, _2982],
dif(_2970, _2982),
dif(_2970, _2976),
dif(_2976, _2982) ;
Set = [_3388, _3394, _3400, _3406],
dif(_3388, _3406),
dif(_3388, _3400),
dif(_3388, _3394),
dif(_3400, _3406),
dif(_3394, _3400),
dif(_3394, _3406) .
?- real_actual_set([A, B, C]), A = 1, B = 2, C = 3.
A = 1,
B = 2,
C = 3.
?- real_actual_set([A, B, C]), A = 1, B = 1, C = 3.
false.
This is quadratic, so it's "less performant" than other approaches. But as John Ousterhout is quoted, "The best performance improvement is the transition from the nonworking state to the working state."

The correct way to check if a list is a set in Prolog is to sort it, removing duplicates, and check if its length is still the same. This is correct for all kinds of reasons, from very pragmatic (easy to program) to purely theoretic (it is the only robust approach to checking if a singly linked list is a set).
"But this is not what I asked" sure it isn't.
is_set(List) :-
sort(List, Sorted),
length(List, N),
length(Sorted, N).
Don't throw Bloom filters and the like at me, at least not without proper justification.
To address the comments by #IsabelleNewbie, if you really want to use attributed variables to make sure that a list will forever remain a set under unification, you would do:
all_different([]).
all_different([H|T]) :-
maplist(dif(H), T),
all_different(T).
but this is a different thing altogether. You also shouldn't use it unless you want to take a list with variables and make sure no two elements in this list will ever unify. You get answers like this (in SWI-Prolog):
?- all_different(X).
X = [] ;
X = [_] ;
X = [_A, _B],
dif(_A, _B) ;
X = [_A, _B, _C],
dif(_A, _B),
dif(_A, _C),
dif(_B, _C) ;
X = [_A, _B, _C, _D],
dif(_A, _B),
dif(_A, _D),
dif(_A, _C),
dif(_B, _D),
dif(_B, _C),
dif(_C, _D) .
I suspect you can find this code in other places too.

For example If I do X = [1,2,3] and than pass it as a argument like isSet(X) it should give me true but instead it generates an error.
You should show us exactly what you tried!
This works:
?- Xs = [1, 2, 3], isSet(Xs).
Xs = [1, 2, 3].
Note that both parts (binding Xs and testing it) are in one query. Maybe you tried entering them separately:
?- Xs = [1, 2, 3].
Xs = [1, 2, 3].
?- isSet(Xs).
false.
This doesn't work because the value of Xs is not saved from one query to the next. This still isn't an error, though. However, it is not great behavior because failing for isSet(Xs) seems to imply that no sets exist at all.

Related

How to create a infinite list if input is not delcared?

I have a written a functional function that tells the user if a list is ordered or not, given the list inputted. However, if a user inputs a variable as the input instead of a list, I would like to output an infinite list. How can I go about this? Here is the current code
ordered([]).
ordered([_]).
ordered([X,Y|Ys]) :- X =< Y , ordered( [Y|Ys] ).
Here is some input
? ordered([1,2,3]).
true
? ordered([1,5,2]).
false
I also want for variables to creat infinite list like so
? ordered(L).
L = [];
L = [_1322] ;
L = [_1322, _1323] ;
L = [_1322, _1323, _1324] ;
L = [_1322, _1323, _1324, _1325].
The list should increase until the user exits as shown.
The list should increase until the user exits as shown.
Solution:
ordered([]).
ordered([_]).
ordered([X,Y|Ys]) :- X #=< Y , ordered( [Y|Ys] ).
EDIT:
SWI Prolog doc
The arithmetic expression X is less than or equal to Y. When reasoning over integers, replace (=<)/2 by #=</2 to obtain more general relations. See declarative integer arithmetic (section A.9.3).
What properties should the list of variables have? The currently accepted answer by Anton Danilov says that [3, 2, 1] is not an ordered list:
?- List = [A, B, C], List = [3, 2, 1], ordered(List).
false.
but it also says that [3, 2, 1] is an instance of an ordered list:
?- List = [A, B, C], ordered(List), List = [3, 2, 1].
List = [3, 2, 1],
A = 3,
B = 2,
C = 1 ;
false.
Viewed logically, this is a contradiction. Viewed procedurally, it is fine, but also the #=< relationship between the variables in the list is meaningless. The comparison of the unbound variables does not say anything about the relationship of the list elements if they are bound to values at some point.
You can use constraints to exclude future unordered bindings:
:- use_module(library(clpfd)).
ordered([]).
ordered([_]).
ordered([X, Y | Xs]) :-
X #=< Y,
ordered([Y | Xs]).
This way you cannot bind the variables in the list to incorrect numbers later on:
?- List = [A, B, C], List = [3, 2, 1], ordered(List).
false.
?- List = [A, B, C], ordered(List), List = [3, 2, 1].
false.
But later correct ordered bindings are still allowed:
?- List = [A, B, C], ordered(List), List = [1, 2, 3].
List = [1, 2, 3],
A = 1,
B = 2,
C = 3 ;
false.
This may not be the best solution, but I believe it can give you some idea of how to do what you need. In SWI-Prolog, the predicate freeze(+Var,:Goal) delays the execution of Goal until Var is bound.
ordered([]).
ordered([_]).
ordered([X,Y|R]) :-
freeze( X,
freeze( Y,
( X #=< Y,
ordered([Y|R]) ) ) ).
Here are some examples with finite lists:
?- ordered([1,2,3]).
true.
?- ordered([1,2,3,0]).
false.
?- ordered(L), L=[1,2,3].
L = [1, 2, 3] ;
false.
?- ordered(L), L=[1,2,3,0].
false.
For an infinite list, you will need to "take" its prefix:
take([]).
take([_|R]) :- take(R).
Here is an example with infinite list:
?- ordered(L), take(L).
L = [] ;
L = [_375396] ;
L = [_376366, _376372],
freeze(_376366, freeze(_376372, (_376366#=<_376372, ordered([])))) ;
L = [_377472, _377478, _377484],
freeze(_377472, freeze(_377478, (_377472#=<_377478, ordered([_377484])))) ;
L = [_378590, _378596, _378602, _378608],
freeze(_378590, freeze(_378596, (_378590#=<_378596, ordered([_378602, _378608])))) ;
L = [_379720, _379726, _379732, _379738, _379744],
freeze(_379720, freeze(_379726, (_379720#=<_379726, ordered([_379732, _379738, _379744]))))

Get index of given element in list

I am trying to solve some basic puzzles to learn prolog. I am trying to get the index of a given element in a list with recursion. I got stuck trying to solve the problem and I am not sure why. When I execute this it only returns "false" instead of the index.
elem(_, [], 0).
elem(E, [E | T], RES) :-
elem(E, T, CUR_RES), RES is CUR_RES + 1.
An example query I use to check the code elem(2, [1, 2], X).
Your problem with
elem(2, [1, 2], X).
is that when it tries to unify with the base case
elem(_, [], 0).
it fails because the second parameter is not empty.
When it tries to unify with the recursive case
elem(E, [E | T], RES) :-
elem(E, T, CUR_RES),
RES is CUR_RES + 1.
E is 2, which requires the list to be [2|T] but since the list is [1,2] it also can not unify.
This is closer to what you want
elem(E,[E|_],0).
elem(E,[_|T],Res) :-
elem(E,T,Cur_rest),
Res is Cur_rest + 1.
Example runs:
?- elem(2, [1, 2], X).
X = 1 ;
false.
?- elem(1, [1, 2], X).
X = 0 ;
false.
?- elem(4, [1,2,3,4,5], X).
X = 3 ;
false.
You need to do the matching for the value you are seeking in the base case and not the recursive case. Once you do that the rest of changes follow as needed.

Prolog : Iterating over a list and creating a predicate

I'm creating a predicate enum that takes a list and a number for example [1,2,3,4] and 3 and returns a list that contains lists of length 3 made out of the list introduced. So in the example given enum([1,2,3,4],3,[[1,2,3],[2,3,4]]).
I've created a function take that takes only the first list of length N but I get errors when I try to loop it to get all of the others. Thanks you for helping.
append([],L,L).
append([H|T],L2,[H|L3]):- append(T,L2,L3).
len([],0).
len([_|B],X):- len(B,X1), X is X1+1.
take(_,X,Y) :- X =< 0, !, X =:= 0, Y = [].
take([],_,[]).
take([A|B],X,[A|C]):- Z is X-1, take(B,Z,C).
enum([],_,[]).
enum([N1|N2],N3,N4):-
len([N1|N2],U),
N3=<U,
take([N1|N2],N3,T1),
append([N4],[T1],T2),
!,
enum(N2,N3,T2).
I will focus on the take/3 predicate, which is the core of your question. In order to get a sublist like [2,3,4] of [1,2,3,4], you have to be able to skip the first element and just take a sublist of the rest.
You can achieve this by adding this clause to your definition:
take([_|Xs], N, Ys) :- take(Xs, N, Ys).
With this you now get several different sublists of length 3, but also some other superfluous solutions:
?- take([1,2,3,4], 3, Xs).
Xs = [1, 2, 3] ;
Xs = [1, 2, 4] ;
Xs = [1, 2] ;
Xs = [1, 3, 4] ;
Xs = [1, 3] ;
Xs = [1, 4] ;
Xs = [1] % etc.
This is because your clause take([], _, []) accepts an empty list as a "sublist of any length" of an empty list. I think you only wanted to accept the empty list as a sublist of length 0. If you remove this clause, your first clause will enforce that, and you only get solutions of length exactly 3:
?- take([1,2,3,4], 3, Xs).
Xs = [1, 2, 3] ;
Xs = [1, 2, 4] ;
Xs = [1, 3, 4] ;
Xs = [2, 3, 4] ;
false.
As a side note, your first clause is fine as is, but it can be simplified a bit to:
take(_,X,Y) :- X = 0, !, Y = [].
I would also advise you to use more readable variable names. For numbers like list lengths, we often use N. For lists, it's customary to use names like Xs, Ys, etc., with X, Y, etc. for members of the corresponding list.
Finally, to find all solutions of a predicate, you need to use a system predicate like setof, bagof, or findall. There is no way to write your enum in pure Prolog.
Because I am not sure about the advice in the other answer, here is my take on your problem.
First, don't define your own append/3 and length/2, append/3 is by now Prolog folklore, you can find it in textbooks 30 years old. And length/2 is really difficult to get right on your own, use the built-in.
Now: to take the first N elements at the front of a list L, you can say:
length(Front, N),
append(Front, _, L)
You create a list of the length you need, then use append/3 to split off this the front from the list you have.
With this in mind, it would be enough to define a predicate sliding_window/3:
sliding_window(L, N, [L]) :-
length(L, N).
sliding_window(L, N, [W|Ws]) :-
W = [_|_], % W should be at least one long
length(W, N),
append(W, _, L),
L = [_|L0],
sliding_window(L0, N, Ws).
This kind of works, but it will loop after giving you all useful answers:
?- sliding_window([a,b], N, Ws).
N = 2,
Ws = [[a, b]] ;
N = 1,
Ws = [[a], [b]] ;
% loops
It loops because of the same little snippet:
length(Front, N),
append(Front, _, L)
With length/2, you keep on generating lists of increasing length; once Front is longer than L, the append/3 fails, length/2 makes an even longer list, and so on forever.
One way out of this would be to use between/3 to constrain the length of the front. If you put it in its own predicate:
front_n(L, N, F) :-
length(L, Max),
between(1, Max, N),
length(F, N),
append(F, _, L).
With this:
sliding_window(L, N, [L]) :-
length(L, N).
sliding_window(L, N, [W|Ws]) :-
front_n(L, N, W),
L = [_|L0],
sliding_window(L0, N, Ws).
And now it finally works:
?- sliding_window([a,b,c,d], 3, Ws).
Ws = [[a, b, c], [b, c, d]] ;
false.
?- sliding_window([a,b,c], N, Ws).
N = 3,
Ws = [[a, b, c]] ;
N = 1,
Ws = [[a], [b], [c]] ;
N = 2,
Ws = [[a, b], [b, c]] ;
false.
Exercise: get rid of the harmless, but unnecessary choice point.

ERROR: Out of global stack with append/3

I have a problem. I want to implement a replace(E1, L1, E2, L2) predicate.
This holds when L1 and L2 are the same lists,except that in one place where L1 has the value E1, L2 has E2. In addition, only one occurrence is replaced and it must work in any mode.
For example:
replace(2,[1,2,3,4],5,X) should have only the solution X = [1,5,3,4].
replace(2,[1,2,3,2,1],5,X) should backtrack over the solutions X =
[1,5,3,2,1] and X = [1,2,3,5,1].
replace(2,X,5,[1,5,3,5,1]) should backtrack over the solutions X =
[1,2,3,5,1] and X = [1,5,3,2,1].
replace(X,[a,b,c,d],Y,[a,e,c,d]) should have only the solution X = b,
Y = e.
replace(X,[1,2,3,2,1],Y,[1,5,3,5,1]) should have no solutions (it
should fail).
My implementation:
replace(E1, L1, E2, L2) :-
append(X, [E1|L_Tail], L1),
append(X, [E2|L_Tail], L2).
This code is fine. However when replace(2,X,5,[1,5,3,5,1]), it should return X = [1,2,3,5,1] and X = [1,5,3,2,1] and false. It only return the first 2 results, and the false didn't came up. The program end up with ERROR: Out of global stack.
This question has been asked and it has two answers: the one you used and a better one. However, I will answer the question "why does this solution not work and how to fix it?".
When the third argument to append/3 is a variable or a partial list, it gives infinitely many solutions:
?- append(X, Y, [a|Z]).
X = [],
Y = [a|Z] ;
X = [a],
Y = Z ;
X = [a, _1860],
Z = [_1860|Y] ;
X = [a, _1860, _1872],
Z = [_1860, _1872|Y] ;
X = [a, _1860, _1872, _1884],
Z = [_1860, _1872, _1884|Y] . % and so on
So, when the first list L1 is a partial list, the call to append(X, [E1|Y], L1) will keep "hallucinating" longer and longer lists. The second call to append/3 will fail every time, Prolog will backtrack, make an even longer list with the first append/3, and so on. This is why you are caught in an infinite loop and will eventually run out of memory (when the lists get too long).
One cheap way to avoid this is to make sure that both lists are proper lists of the same length before giving them to the two appends. For example:
same_length([], []).
same_length([_|A], [_|B]) :- same_length(A, B).
If you are using SWI-Prolog you could do this with maplist and a yall lambda:
maplist([_,_]>>true, L1, L2)
The example query:
?- L2 = [1,5,3,5,1],
maplist([_,_]>>true, L1, L2),
append(X, [2|Y], L1),
append(X, [5|Y], L2).
L2 = [1, 5, 3, 5, 1],
L1 = [1, 2, 3, 5, 1],
X = [1],
Y = [3, 5, 1] ;
L2 = [1, 5, 3, 5, 1],
L1 = [1, 5, 3, 2, 1],
X = [1, 5, 3],
Y = [1] ;
false.

Most general higher-order constraint describing a sequence of integers ordered with respect to a relation

In CLP(FD), we frequently need to state: "This is a list of integers and finite domain variables in (sometimes: strictly) ascending/descending order."
Is there any CLP(FD) system that provides a general (parametrisable) built-in constraint for this task?
SWI-Prolog provides a constraint called chain/2, which is similar to what I am looking for. However, the name is slightly too specific to encompass all relations that the constraint can describe (example: #< is not a partial order but admissible in chain/2, leading to the sequence — taken as a set of integers — no longer counting as a chain as defined in mathematical order-theory). Hence, the name does not fully describe what the constraint actually implements.
Please give the most general definition with respect to the usual binary CLP(FD) constraints — or a suitable subset that contains at least #<, #>, #=< and #>= — including the proper name according to the algebraic structure the constraint defines. The condition imposed is that the constraint describe an actual mathematical structure that has a proper name in the literature.
As a start, consider with SICStus Prolog or SWI:
:- use_module(library(clpfd)).
connex(Relation_2, List) :-
connex_relation(Relation_2),
connex_(List, Relation_2).
connex_relation(#=).
connex_relation(#<).
connex_relation(#=<).
connex_relation(#>).
connex_relation(#>=).
connex_([], _).
connex_([L|Ls], Relation_2) :-
foldl(adjacent(Relation_2), Ls, L, _).
adjacent(Relation_2, X, Prev, X) :- call(Relation_2, Prev, X).
Sample cases:
?- connex(#<, [A,B,C]).
A#=<B+-1,
B#=<C+-1.
?- connex(#=, [A,B,C]).
A = B, B = C,
C in inf..sup.
?- maplist(connex(#<), [[A,B],[C,D]]).
A#=<B+-1,
C#=<D+-1.
Notice that it would even be admissible to allow #\=, because the relation would still describe a connex as known in mathematical order-theory. Hence, the code above is not most general with respect to the usual binary CLP(FD) constraints.
Hoogle was not very useful, but Hayoo is!
foldcmpl
so this is a special form of fold for a list, but it does not apply length list times but one time less.
isSortedBy
is not entirely general in its name, but in its signature. Maybe insisting on the most general name is not that helpful. Otherwise we just have entities all over?
The definition reads:
The isSortedBy function returns True iff the predicate returns true for all adjacent pairs of elements in the list.
Maybe: all_adjacent_pairs(R_2, Xs). which sounds a bit after having a looping construct that has adjacent_pair as some modifier.
This is inspired by a toolbox of functional higher-order idioms I once implemented. Back then I found the corner cases agonizing, I still do today:) Also, finding good names is always an issue...
Consider meta-predicate mapadj/4:
mapadj(Relation_4,As,Bs,Cs) :-
list_list_list_mapadj(As,Bs,Cs,Relation_4).
list_list_list_mapadj([],[],[],_).
list_list_list_mapadj([A|As],Bs,Cs,Relation_4) :-
list_prev_list_list_mapadj(As,A,Bs,Cs,Relation_4).
list_prev_list_list_mapadj([],_,[],[],_).
list_prev_list_list_mapadj([A1|As],A0,[B|Bs],[C|Cs],Relation_4) :-
call(Relation_4,A0,A1,B,C),
list_prev_list_list_mapadj(As,A1,Bs,Cs,Relation_4).
Sample uses:
z_z_sum_product(X,Y,Sum,Product) :-
Sum #= X + Y,
Product #= X * Y.
:- mapadj(z_z_sum_product,[], [], []).
:- mapadj(z_z_sum_product,[1], [], []).
:- mapadj(z_z_sum_product,[1,2], [3], [2]).
:- mapadj(z_z_sum_product,[1,2,3], [3,5], [2,6]).
:- mapadj(z_z_sum_product,[1,2,3,4],[3,5,7],[2,6,12]).
I'm aware of the rift in the corner cases As = []and As = [_], still I feel this is as close to "for all adjacent list items" as it gets.
Also, all of this can easily be extended:
down to mapadj/2 (akin to chain/2, except for the type-check with singleton lists)
sideways, with an additional state argument, to foldadjl/n, scanadjl/n
Regarding names: IMO the l / r suffix is required with fold / scan, but not with map.
Edit 2015-04-26
Here comes the before-mentioned foldadjl/4:
foldadjl(Relation_4,Xs) -->
list_foldadjl(Xs,Relation_4).
list_foldadjl([],_) -->
[].
list_foldadjl([X|Xs],Relation_4) -->
list_prev_foldadjl(Xs,X,Relation_4).
list_prev_foldadjl([],_,_) -->
[].
list_prev_foldadjl([X1|Xs],X0,Relation_4) -->
call(Relation_4,X0,X1),
list_prev_foldadjl(Xs,X1,Relation_4).
Edit 2015-04-27
Here comes meta-predicate splitlistIfAdj/3, based on
if_/3 which was proposed in a previous answer
on reification.
split_if_adj(P_3,As,Bss) :- splitlistIfAdj(P_3,As,Bss).
splitlistIfAdj(P_3,As,Bss) :-
list_split_(As,Bss,P_3).
list_split_([],[],_).
list_split_([X0|Xs], [Cs|Bss],P_3) :-
list_prev_split_(Xs,X0,Cs,Bss, P_3).
list_prev_split_([], X, [X],[],_).
list_prev_split_([X1|Xs],X0,[X0|Cs],Bss,P_3) :-
if_(call(P_3,X0,X1),
(Cs = [], Bss = [Cs0|Bss0]),
(Cs = Cs0, Bss = Bss0)),
list_prev_split_(Xs,X1,Cs0,Bss0,P_3).
To show it in use let's define dif/3 exactly the same way as (=)/3 but with flipped truth-value:
dif(X, Y, R) :- X == Y, !, R = false.
dif(X, Y, R) :- ?=(X, Y), !, R = true. % syntactically different
dif(X, Y, R) :- X \= Y, !, R = true. % semantically different
dif(X, Y, R) :- R == false, !, X = Y.
dif(X, X, false).
dif(X, Y, true) :-
dif(X, Y).
Now we use them in tandem:
?- splitlistIfAdj(dif,[1,2,2,3,3,3,4,4,4,4],Pss).
Pss = [[1],[2,2],[3,3,3],[4,4,4,4]]. % succeeds deterministically
What if we generalize some list items? Do we get multiple answers with the right pending goals?
First, a small example:
?- splitlistIfAdj(dif,[1,X,2],Pss).
X = 1, Pss = [[1,1],[2]] ;
X = 2, Pss = [[1],[2,2]] ;
dif(X,1),dif(X,2), Pss = [[1],[X],[2]].
A somewhat bigger example involving the two variables X and Y.
?- splitlistIfAdj(dif,[1,2,2,X,3,3,Y,4,4,4],Pss).
X = 2, Y = 3, Pss = [[1],[2,2,2],[3,3,3],[4,4,4]] ;
X = 2, Y = 4, Pss = [[1],[2,2,2],[3,3],[4,4,4,4]] ;
X = 2, dif(Y,3),dif(Y,4), Pss = [[1],[2,2,2],[3,3],[Y],[4,4,4]] ;
X = Y, Y = 3, Pss = [[1],[2,2],[3,3,3,3],[4,4,4]] ;
X = 3, Y = 4, Pss = [[1],[2,2],[3,3,3],[4,4,4,4]] ;
X = 3, dif(Y,3),dif(Y,4), Pss = [[1],[2,2],[3,3,3],[Y],[4,4,4]] ;
dif(X,2),dif(X,3), Y = 3, Pss = [[1],[2,2],[X],[3,3,3],[4,4,4]] ;
dif(X,2),dif(X,3), Y = 4, Pss = [[1],[2,2],[X],[3,3],[4,4,4,4]] ;
dif(X,2),dif(X,3), dif(Y,3),dif(Y,4), Pss = [[1],[2,2],[X],[3,3],[Y],[4,4,4]].
Edit 2015-05-05
Here's tpartition/4:
tpartition(P_2,List,Ts,Fs) :- tpartition_ts_fs_(List,Ts,Fs,P_2).
tpartition_ts_fs_([],[],[],_).
tpartition_ts_fs_([X|Xs0],Ts,Fs,P_2) :-
if_(call(P_2,X), (Ts = [X|Ts0], Fs = Fs0),
(Ts = Ts0, Fs = [X|Fs0])),
tpartition_ts_fs_(Xs0,Ts0,Fs0,P_2).
Sample use:
?- tpartition(=(0), [1,2,3,4,0,1,2,3,0,0,1], Ts, Fs).
Ts = [0, 0, 0],
Fs = [1, 2, 3, 4, 1, 2, 3, 1].
Edit 2015-05-15
On and on, ... here's splitlistIf/3:
split_if(P_2,As,Bss) :- splitlistIf(P_2,As,Bss).
splitlistIf(P_2,As,Bss) :-
list_pred_split(As,P_2,Bss).
list_pred_split([],_,[]).
list_pred_split([X|Xs],P_2,Bss) :-
if_(call(P_2,X), list_pred_split(Xs,P_2,Bss),
(Bss = [[X|Ys]|Bss0], list_pred_open_split(Xs,P_2,Ys,Bss0))).
list_pred_open_split([],_,[],[]).
list_pred_open_split([X|Xs],P_2,Ys,Bss) :-
if_(call(P_2,X), (Ys = [], list_pred_split(Xs,P_2,Bss)),
(Ys = [X|Ys0], list_pred_open_split(Xs,P_2,Ys0,Bss))).
Let's use it:
?- splitlistIf(=(x),[x,1,2,x,1,2,3,x,1,4,x,x,x,x,1,x,2,x,x,1],Xs).
Xs = [[1, 2], [1, 2, 3], [1, 4], [1], [2], [1]].
Quite in the same vein as mapadj/4 presented in an earlier answer... maybe the name is better.
forallAdj(P_2,Xs) :-
list_forallAdj(Xs,P_2).
list_forallAdj([],_).
list_forallAdj([X|Xs],P_2) :-
list_forallAdj_prev(Xs,P_2,X).
list_forallAdj_prev([],_,_).
list_forallAdj_prev([X1|Xs],P_2,X0) :-
call(P_2,X0,X1),
list_forallAdj_prev(Xs,P_2,X1).
Sample use:
:- use_module(library(clpfd)).
:- use_module(library(lambda)).
?- Ls = [0,_,_,_,_,_], forallAdj(\X0^X1^(X0 + 1 #= X1), Ls).
Ls = [0, 1, 2, 3, 4, 5].
Where could that take us?
forallAdj => existAdj
maybe variants with index (forallAdjI, existAdjI) like in Collections.List Module (F#)
findfirstAdj/pickfirstAdj also like F# find/pick

Resources