Related
I'm trying to split a list into the items before a specific element (specifically the word "stop") as well as the items after this element. I know you can use split to do this, but I'm new to prolog and so I'm trying to manipulate things without using these functions currently, and so I'd really like to know if this is possible? (and maybe some pointers in the right direction)
i.e. with the list;
L = [tea,coffee,sugar,cake,stop,meat,fish,eggs,flour]
I'd ideally want to split the list at 'stop' leaving me with,
L2 = [tea, coffee, sugar, cake] // and
L3 = [meat, fish, eggs, flour]
Using seq//1:
list_splitonstop(Xs, As, Bs) :-
phrase( ( seq(As), [stop], seq(Bs) ), Xs).
This version works as you expected:
?- L = [tea,coffee,sugar,cake,stop,meat,fish,eggs,flour],
list_splitonstop(L, L1, L2).
L = [tea,coffee,sugar,cake,stop,meat,fish,eggs,flour],
L1 = [tea,coffee,sugar,cake], L2 = [meat,fish,eggs,flour]
; false.
But, is it really the best solution? This ; false at the end may be an indication that it is not. But we cannot say this for sure. We would have to figure out another case where this solution does not work as expected. You are faced with similar problems also in other programming languages were one has to rely a lot on the imagination of the programmer to find out border cases and the like.
Fortunately, we are here using Prolog which helps us to understand what we are actually defining.
A very simple first start is to ask the most general query. Just like that:
?- list_splitonstop(L, L1, L2).
L = [stop], L1 = [], L2 = []
; L = [stop,_A], L1 = [], L2 = [_A]
; L = [stop,_A,_B], L1 = [], L2 = [_A,_B]
; L = [stop,_A,_B,_C], L1 = [], L2 = [_A,_B,_C]
; ... .
Look at each answer! Let's take the third as an example. L = [stop,_A,_B] means that this answer includes all lists with three elements where the first is stop. So we are looking here at an infinity of solutions that have been all compactly described with a couple of characters! Not even bzip2 -99 can do that!
Are these the only lists with three elements? We cannot say this from this single query alone, for Prolog might enumerate answers in an unfair manner. Imagine you ask someone to tell you all the natural numbers, but that person starts 0, 2, 4, ... Evidently, that enumeration is very unfair to the odd numbers. Similarly some answers might be missing ...
In Prolog we can insist on looking at lists of length 3 only:
?- L = [_,_,_], list_splitonstop(L, L1, L2).
L = [stop,_A,_B], L1 = [], L2 = [_A,_B]
; L = [_A,stop,_B], L1 = [_A], L2 = [_B]
; L = [_A,_B,stop], L1 = [_A,_B], L2 = []
; false.
So we can ask for all relevant cases of length 3 in a single query. Note that these _A and _B variables represent any term! Please take a moment and appreciate what you are looking at: All cases for lists of length 3. There are no other cases to consider!
When you look at such answers some questions may arise. Like: Do these three answers overlap, or are they truly disjoint? Prolog knows the answer. Simply repeat the actual goal and count the resulting answers:
?- L = [_,_,_], list_splitonstop(L, L1, L2), list_splitonstop(L, L1, L2).
(answers same as above)
So we get exactly the same answers. There is no inherent redundancy.
Another question might be: Does L has always precisely one possible split? (In other words: Does there exist a functional dependency?)
We can get to this by asking for L that have a different L1 and L2:
?- L = [_,_,_], dif(L1-L2,L1x-L2x),
list_splitonstop(L, L1, L2), list_splitonstop(L, L1x, L2x).
L = [stop,stop,_A], L1 = [], L2 = [stop,_A], L1x = [stop], L2x = [_A]
; L = [stop,_A,stop], L1 = [], L2 = [_A,stop], L1x = [stop,_A], L2x = []
; L = [stop,stop,_A], L1 = [stop], L2 = [_A], L1x = [], L2x = [stop,_A]
; L = [_A,stop,stop], L1 = [_A], L2 = [stop], L1x = [_A,stop], L2x = []
; L = [stop,_A,stop], L1 = [stop,_A], L2 = [], L1x = [], L2x = [_A,stop]
; L = [_A,stop,stop], L1 = [_A,stop], L2 = [], L1x = [_A], L2x = [stop]
; false.
So, I may ask you now: Do you want above cases? If there are several occurrences of stop? Clearly, you did not specify this and we need some more information from you. Prolog was at least helpful to identify such cases.
How to identify redundant answers.
In the case above we observed that there are no redundant answers. But how do they show up when they show up? Here is such an example: member/2 which is built-in and produces (sometimes) redundant answers and memberd/2 which does not have this redundancy. The actual question is:
How does a two-element list look like that has e as an element/member?
?- Xs = [_,_], member(e, Xs).
Xs = [e,_A]
; Xs = [_A,e].
?- Xs = [_,_], member(e, Xs), member(e, Xs).
Xs = [e,_A]
; Xs = [e,e] % <--- redundant
; Xs = [e,e] % <--- redundant
; Xs = [_A,e].
?- Xs = [_,_], memberd(e, Xs).
Xs = [e,_A]
; Xs = [_A,e], dif(_A,e)
; false.
?- Xs = [_,_], memberd(e, Xs), memberd(e, Xs).
Xs = [e,_A]
; Xs = [_A,e], dif(_A,e)
; false.
If you are only interested in seeing those answers that permit redundancies, you can say in stead:
?- Xs = [_,_], member(e, Xs), \+ \+ call_nth(member(e, Xs), 2).
Xs = [e,_A]
; Xs = [_A,e].
In other words, all answers of member/2 permit such redundancies. Note that member/2 is not always prone to redundancy. In particular, if the list contains different (nonunifiable) elements, there are no redundancies at all. And this is a frequent use case.
?- Xs = [a,b], member(X, Xs), \+ \+call_nth(member(X, Xs),2).
false.
In fact, in this very case, that is when querying for X, member/2 is probably more efficient than memberd/2.
As said in a comment, a recursive definition is the most natural way to do this:
split_on_stop([], [[]]).
split_on_stop([stop|T], [[]|T2]) :-
split_on_stop(T, T2).
split_on_stop([H|T], [[H|T2]|T3]) :-
dif(H, stop),
split_on_stop(T, [T2|T3]).
This implementation will work with multiple occurences of stop: the second argument is a list of those splitted lists.
The complicated part to figure out here is the contents of that second argument in all three cases (when the first one is empty, when we find a stop, and when we find something other than a stop).
Note
If it is guaranteed that the input list has one and only one stop, you can shorten this implementation a lot (but it loses a lot of desirable behaviours):
split_on_stop([stop|T], [], T).
split_on_stop([H|T], [H|T2], T3) :-
dif(H, stop),
split_on_stop(T, T2, T3).
append/3 is your magic sword:
split_on_stop(List, Before, After) :-
append(Before, [stop|After], List).
No more, no less, so in most cases you just inline the append goal.
I need to convert a list of elements into a list of lists.
For example, if i have the list [1,2,3,4] the output must be [[1],[2],[3],[4]], one element per list.
create([],_, _, _).
create([H|T], Aux, X, Result) :-
append([H], Aux, X),
Result = [X],
create(T, X, _, Result).
I always get false... is this even possible to do?
Another possibility to define this relation is by using DCGs. They yield easily readable code when describing lists. Let's stick with the name singletons as suggested by #false in the comments:
singletons([]) --> % the empty list
[]. % is empty
singletons([H|T]) --> % the head of a nonempty list
[[H]], % is a list on its own
singletons(T). % and so is the tail
You can query this directly with phrase/2:
?- phrase(singletons([1,2,3,4]),X).
X = [[1],[2],[3],[4]]
Or write a wrapper-predicate with phrase/2 as the single goal:
singletons(L,Ls) :-
phrase(singletons(L),Ls).
And query that:
?- singletons([1,2,3,4],Ls).
Ls = [[1],[2],[3],[4]]
The predicate also works the other way around:
?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4] ? ;
no
As well as the most general query:
?- singletons(L,Ls).
L = Ls = [] ? ;
L = [_A],
Ls = [[_A]] ? ;
L = [_A,_B],
Ls = [[_A],[_B]] ?
...
Alternatively you can also define a simple predicate that describes a relation between an arbitrary element and itself in brackets and then use maplist/3 from library(apply) to apply it on every element of a list:
:- use_module(library(apply)).
embraced(X,[X]).
singletons(L,Ls) :-
maplist(embraced,L,Ls).
This version yields the same results for the above queries. However, it is more efficient. To see that consider the following query from above:
?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4]
Above you had to enter ; to make Prolog search for further solutions and subsequently fail (indicated by no). With this version there are no unnecessary choice points left and Prolog is succeeding deterministically for the query.
Try this
create([],[]).
create([H|T],[[H]|T2]):- create(T,T2).
I tried
?- create([1,2,3,4],X).
and the result was
X = [[1], [2], [3], [4]].
I would solve it by comparing the first index of the first list and adding 2 to the index. But I do not know how to check for indexes in prolog.
Also, I would create a counter that ignores what is in the list when the counter is an odd number (if we start to count from 0).
Can you help me?
Example:
everyOther([1,2,3,4,5],[1,3,5]) is true, but everyOther([1,2,3,4,5],[1,2,3]) is not.
We present three logically-pure definitions even though you only need one—variatio delectat:)
Two mutually recursive predicates list_oddies/2 and skipHead_oddies/2:
list_oddies([],[]).
list_oddies([X|Xs],[X|Ys]) :-
skipHead_oddies(Xs,Ys).
skipHead_oddies([],[]).
skipHead_oddies([_|Xs],Ys) :-
list_oddies(Xs,Ys).
The recursive list_oddies/2 and the non-recursive list_headless/2:
list_oddies([],[]).
list_oddies([X|Xs0],[X|Ys]) :-
list_headless(Xs0,Xs),
list_oddies(Xs,Ys).
list_headless([],[]).
list_headless([_|Xs],Xs).
A "one-liner" which uses meta-predicate foldl/4 in combination with Prolog lambdas:
:- use_module(library(lambda)).
list_oddies(As,Bs) :-
foldl(\X^(I-L)^(J-R)^(J is -I,( J < 0 -> L = [X|R] ; L = R )),As,1-Bs,_-[]).
All three implementations avoid the creation of useless choicepoints, but they do it differently:
#1 and #2 use first-argument indexing.
#3 uses (->)/2 and (;)/2 in a logically safe way—using (<)/2 as the condition.
Let's have a look at the queries #WouterBeek gave in his answer!
?- list_oddies([],[]),
list_oddies([a],[a]),
list_oddies([a,b],[a]),
list_oddies([a,b,c],[a,c]),
list_oddies([a,b,c,d],[a,c]),
list_oddies([a,b,c,d,e],[a,c,e]),
list_oddies([a,b,c,d,e,f],[a,c,e]),
list_oddies([a,b,c,d,e,f,g],[a,c,e,g]),
list_oddies([a,b,c,d,e,f,g,h],[a,c,e,g]).
true. % all succeed deterministically
Thanks to logical-purity, we get logically sound answers—even with the most general query:
?- list_oddies(Xs,Ys).
Xs = [], Ys = []
; Xs = [_A], Ys = [_A]
; Xs = [_A,_B], Ys = [_A]
; Xs = [_A,_B,_C], Ys = [_A,_C]
; Xs = [_A,_B,_C,_D], Ys = [_A,_C]
; Xs = [_A,_B,_C,_D,_E], Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F], Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F,_G], Ys = [_A,_C,_E,_G]
; Xs = [_A,_B,_C,_D,_E,_F,_G,_H], Ys = [_A,_C,_E,_G]
...
There are two base cases and one recursive case:
From an empty list you cannot take any odd elements.
From a list of length 1 the only element it contains is an odd element.
For lists of length >2 we take the first element but not the second one; the rest of the list is handled in recursion.
The code looks as follows:
odd_ones([], []).
odd_ones([X], [X]):- !.
odd_ones([X,_|T1], [X|T2]):-
odd_ones(T1, T2).
Notice that in Prolog we do not need to maintain an explicit index that has to be incremented etc. We simply use matching: [] matches the empty list, [X] matches a singleton list, and [X,_|T] matches a list of length >2. The | separates the first two elements in the list from the rest of the list (called the "tail" of the list). _ denotes an unnamed variable; we are not interested in even elements.
Also notice the cut (!) which removes the idle choicepoint for the second base case.
Example of use:
?- odd_ones([], X).
X = [].
?- odd_ones([a], X).
X = [a].
?- odd_ones([a,b], X).
X = [a].
?- odd_ones([a,b,c], X).
X = [a, c].
?- odd_ones([a,b,c,d], X).
X = [a, c].
?- odd_ones([a,b,c,d,e], X).
X = [a, c, e].
How I can add an element E right after the first occurrence of X in list Xs?
Example:
?- insert_right_behind(5,10,[2,4,10,12],Xs).
Xs = [2,4,10,5,12]. % expected answer
At this moment, I have problems understanding
the recursion that needs to be made since I am new to the language.
Thanks in advance!
In the previous answer most successful queries left behind useless choicepoints.
We can avoid these choicepoints by using if_/3 and (=)/3 like so:
item_following_in_inserted(I,J,[X|Xs],Ys0) :-
if_(J = X,
Ys0 = [J,I|Xs],
(Ys0 = [X|Ys], item_following_in_inserted(I,J,Xs,Ys))).
Let's run some queries!
?- item_following_in_inserted(5,10,[2,4,12],Xs).
false. % OK, unchanged
?- item_following_in_inserted(5,10,[2,4,10,12],Xs).
Xs = [2,4,10,5,12]. % succeeds deterministically
?- item_following_in_inserted(5,10,[2,4,10,12,10],Xs).
Xs = [2,4,10,5,12,10]. % succeeds deterministically
?- item_following_in_inserted(I,E,Xs,Ys).
Xs = [ E|_Z], Ys = [ E,I|_Z] % OK, unchanged
; Xs = [ _A,E|_Z], Ys = [ _A,E,I|_Z], dif(E,_A)
; Xs = [_A,_B,E|_Z], Ys = [_A,_B,E,I|_Z], dif(E,_A), dif(E,_B)
...
Use three predicate clauses:
% Inserting after in an empty list is an empty list:
insert_after( _X, _Y, [], [] ).
% If the "after" item is at the head of the list, then the "insert" item can go after it:
insert_after( X, Y, [Y|T], [Y,X|T] ).
% If the head of the list isn't the "after" item, then the result will be
% this with a new tail list that has the "insert" item inserted:
insert_after( X, Y, [H|T], [H|L] ) :-
Y \= H,
insert_after( X, Y, T, L ).
If the "after" item doesn't exist in the given list, then insert_after/4 will yield the original list. By removing the first insert_after clause above, it will just fail for that case.
Let's keep it simple and use append/3, meta-predicate maplist/2 and prolog-dif like so:
item_following_in_inserted(I,J,Xs,Ys) :-
append(Prefix,[J |Suffix],Xs),
maplist(dif(J),Prefix),
append(Prefix,[J,I|Suffix],Ys).
Done! It's query time... First, let's run the query the OP gave:
?- item_following_in_inserted(5,10,[2,4,10,12],Xs).
Xs = [2,4,10,5,12] % succeeds, but leaves behind choicepoint
; false.
What if the item is not a member of the given list?
?- item_following_in_inserted(5,10,[2,4, 12],Xs).
false. % fails, as expected: 10 is absent
Let's check that we only insert after the first occurrence—and nowhere else!
?- item_following_in_inserted(5,10,[2,4,10,12,10],Xs).
Xs = [2,4,10,5,12,10] % single solution
; false. % terminates universally
What about the most general query of item_following_in_inserted/4?
?- item_following_in_inserted(I,E,Xs,Ys).
Xs = [ E|_Z], Ys = [ E,I|_Z]
; Xs = [ _A,E|_Z], Ys = [ _A,E,I|_Z], dif(E,_A)
; Xs = [ _A,_B,E|_Z], Ys = [ _A,_B,E,I|_Z], dif(E,_A), dif(E,_B)
; Xs = [_A,_B,_C,E|_Z], Ys = [_A,_B,_C,E,I|_Z], dif(E,_A), dif(E,_B), dif(E,_C)
...
I'm having an issue with SWI-Prolog's delete/3 predicate.
The easiest way is just a quick example:
?- delete([(1,1),(1,2),(3,2)], (1,_), List).
List = [(1,2),(3,2)].
I would expect (1,2) to also be deleted, since (1,_) unifies with (1,2). The SWIPL help says:
Delete all members of List1 that simultaneously unify with Elem and unify the result with List2.
Why is this and how can I delete everything that unifies with (1,_)?
" Delete all members of List1 that simultaneously unify with Elem and unify the result with List2."
(1,X) first unifies with (1,1). therefore, X is unified with 1 and cannot be unified with 2 to delete (1,2).
so the problem is not that it does not delete all of the members; it's that it doesnt unify simultaneously with (1,2) and (1,1)
(try delete([(1,1),(1,2),(1,1),(3,2)],(1,_),List).
btw, according to the swi-prolog manual:
delete(?List1, ?Elem, ?List2)
Is true when Lis1, with all occurences of Elem deleted results in List2.
also, delete/3 is deprecated:
There are too many ways in which one might want to delete elements from a list to justify the name.
Think of matching (= vs. ==), delete first/all, be deterministic or not.
So the easiest way is to write your own predicate. Something like:
my_delete(Pattern,[Pattern|T],TD):-
my_delete(Pattern,T,TD).
my_delete(Pattern,[H|T],[H|TD]):-
my_delete(Pattern,T,TD).
perhaps?
check exclude/3, include/3, partition/4
Use meta-predicate texclude/3 in combination with the
reified term equality predicate
(=)/3!
First, we try using (=)/3 directly...
?- texclude(=((1,V)), [(1,1),(1,2),(3,2)], KVs).
KVs = [ (1,2),(3,2)], V=1 ;
KVs = [(1,1), (3,2)], V=2 ;
KVs = [(1,1),(1,2),(3,2)], dif(V,1), dif(V,2).
Not quite! For our next tries we are going to use lambda expressions.
:- use_module(library(lambda)).
Let's query---once with texclude/3, once with tinclude/3, and once with tpartition/4:
?- texclude( \ (K,_)^(K=1), [(1,1),(1,2),(3,2)], Fs).
Fs = [(3,2)]. % succeeds deterministically
?- tinclude( \ (K,_)^(K=1), [(1,1),(1,2),(3,2)], Ts).
Ts = [(1,1),(1,2)]. % succeeds deterministically
?- tpartition(\ (K,_)^(K=1), [(1,1),(1,2),(3,2)], Ts,Fs).
Ts = [(1,1),(1,2)], Fs = [(3,2)]. % succeeds deterministically
Alright! Do we get the same solutions if the list items are bound after the texclude/3 call?
?- texclude(\ (K,_)^(K=1), [A,B,C], Fs), A = (1,1), B = (1,2), C = (3,2).
A = (1,1), B = (1,2), C = (3,2), Fs = [(3,2)] ; % succeeds with choice point
false.
Yes! At last, consider the following quite general query:
?- texclude(\ (K,_)^(K=1), [A,B], Fs).
Fs = [ ], A = ( 1,_A1), B = ( 1,_B1) ;
Fs = [ B], A = ( 1,_A1), B = (_B0,_B1), dif(_B0,1) ;
Fs = [A ], A = (_A0,_A1), B = ( 1,_B1), dif(_A0,1) ;
Fs = [A,B], A = (_A0,_A1), B = (_B0,_B1), dif(_A0,1), dif(_B0,1).
Note that above goals restrict all list items to have the form (_,_). Thus the following query fails:
?- texclude(\ (K,_)^(K=1), [x,_], _).
false.
This answer tries to generalize the idea presented in previous answer.
Let's define a reified variant of subsumes_term/2:
list_nonvardisj([A],C) :-
!,
C = nonvar(A).
list_nonvardisj([A|As],(nonvar(A);C)) :-
list_nonvardisj(As,C).
subsumes_term_t(General,Specific,Truth) :-
subsumes_term(General,Specific),
!,
term_variables(General,G_vars),
free4evrs(G_vars),
Truth = true.
subsumes_term_t(General,Specific,Truth) :-
Specific \= General,
!,
Truth = false.
subsumes_term_t(General,Specific,Truth) :-
term_variables(Specific,S_vars),
( S_vars = [V]
-> freeze(V,subsumes_term_t(General,Specific,Truth))
; S_vars = [_|_]
-> list_nonvardisj(S_vars,S_wakeup),
when(S_wakeup,subsumes_term_t(General,Specific,Truth))
; throw(error(instantiation_error, subsumes_term_t/3))
),
( Truth = true
; Truth = false
).
The above definition of the reified predicate subsumes_term_t/3 uses free4evrs/1 to ensure that the "generic" term passed to subsumes_term/2 is not instantiated any further.
For SICStus Prolog, we can define it as follows:
:- module(free4evr,[free4evr/1,free4evrs/1]).
:- use_module(library(atts)).
:- attribute nvrb/0. % nvrb ... NeVeR Bound
verify_attributes(V,_,Goals) :-
get_atts(V,nvrb),
!,
Goals = [throw(error(uninstantiation_error(V),free4evr/1))].
verify_attributes(_,_,[]).
attribute_goal(V,free4evr(V)) :-
get_atts(V,nvrb).
free4evr(V) :-
nonvar(V),
!,
throw(error(uninstantiation_error(V),free4evr/1)).
free4evr(V) :-
( get_atts(V,nvrb)
-> true
; put_atts(Fresh,nvrb),
V = Fresh
).
free4evrs([]).
free4evrs([V|Vs]) :-
free4evr(V),
free4evrs(Vs).
Let's put subsumes_term_t/3 to use!
?- texclude(subsumes_term_t(1-X), [A,B,C], Fs), A = 1-1, B = 1-2, C = 3-2.
A = 1-1, B = 1-2, C = 3-2, Fs = [C], free4evr(X) ? ; % succeeds with choice-point
no
?- texclude(subsumes_term_t(1-X), [x,1-Y,2-3], Fs).
Fs = [x,2-3], free4evr(X) ? ;
no
What happens if we instantiate variable X in above query sometime after the call to texclude/3?
?- texclude(subsumes_term_t(1-X), [x,1-Y,2-3], Fs), X=something.
! error(uninstantiation_error(something),free4evr/1)