Prolog get every second Item in a list - list

I want to write a Prolog predicate
evenElement(List,Term) which shoud suceed if the EvenElement is equal to Term
So far I have this code
evenElement(L,TERM) :- evenElement_rec(L,TERM).
evenElement_rec([],0).
evenElement_rec([_,HEven|T],TERM):-
evenElement_rec(T,TERM),
isEqual(HEven,TERM).
isEqual(A,B) :- A is B.
isEqual is never called, what do I have to change that this will be executed?
output is:
trace,evenElement([1,2,3,4,5,6], 4).
Call: (7) evenElement([1, 2, 3, 4, 5, 6], 4) ? creep
Call: (8) evenElement_rec([1, 2, 3, 4, 5, 6], 4) ? creep
Call: (9) evenElement_rec([3, 4, 5, 6], 4) ? creep
Call: (10) evenElement_rec([5, 6], 4) ? creep
Call: (11) evenElement_rec([], 4) ? creep
Fail: (11) evenElement_rec([], 4) ? creep
Fail: (10) evenElement_rec([5, 6], 4) ? creep
Fail: (9) evenElement_rec([3, 4, 5, 6], 4) ? creep
Fail: (8) evenElement_rec([1, 2, 3, 4, 5, 6], 4) ? creep
Fail: (7) evenElement([1, 2, 3, 4, 5, 6], 4) ? creep
false.

When you are writing a Prolog predicate, you could start like in other programming languages, digging immediately into the very problem. Or you can first think about the relation, and consider something simpler i.e. more general. You want that the first argument is a list, and the second argument is an "even" element — I assume you meant an element occurring at an even position. That is:
list_evenelement(L, E) :-
nth1(I,L,E),
I mod 2 =:= 0.
But, say you want to implement that yourself. We might start with a generalization. In this case: list_element/2 which is true for all elements:
list_element([E|_], E).
list_element([_|Es], E) :-
list_element(Es, E).
That is almost what you want. Except that it is a bit too general. That is, the set of solutions contains also answers you do not like. In particular, the first element, should not be part of the solutions. You have thus to specialize that program. We can specialize a program by adding a goal or by removing a clause (which is tantamount to adding false). Removing the fact, however, goes too far - there will no longer be any solution.
I will try it differently, and unfold the definition like so:
list_element([E|_], E).
list_element([_|Es], E) :-
list_element2(Es, E).
list_element2([E|_], E).
list_element2([_|Es], E) :-
list_element(Es, E).
That should be still our good olde definition that is too general. Now, however, we can insert false!
list_element([E|_], E) :- false.
list_element([_|Es], E) :-
list_element2(Es, E).
list_element2([E|_], E).
list_element2([_|Es], E) :-
list_element(Es, E).
This remaining part is our sought after definition, you can also put it more compactly:
list_evenelement([_,E|_], E).
list_evenelement([_,_|Es], E) :-
list_evenelement(Es, E).

Your code looks way more complicated than it has any right to be from your problem statement
I want to write a Prolog predicate evenElement(List,Term) which shoud suceed if the EvenElement is equal to Term.
Assuming that you're numbering your list elements relative to one, so for the list [a,b,c,d], the odd elements (1st and 3rd) are a and c respectively and the event elements (2nd and 4th) are b and d (rather than zero-relative, where a would be the zeroth element and c the 2nd, something like this will do. We look at the list, 2 elements at a time:
even_element( [_,T|Xs] , T ) .
even_element( [_,_|Xs] , T ) :-
even_element( Xs , T ) .

Related

Why in SWI Prolog, I get the result with `|` sign?

I have the following code to group sequences of equivalent objects together:
pack([], []).
pack([X], [X]).
pack([H, T|TS], [H|TR]):-
H \= T,
pack([T|TS], TR).
pack([H, H|HS], [[H|TFR]|TR]):-
pack([H|HS], [TFR|TR]).
My input is:
pack([1,1,1,1,2,3,3,1,1,4,5,5,5,5], X).
And as a result I get:
[[1,1,1|1],2,[3|3],[1|1],4,[5,5,5|5]]
Have you noticed | sign before the last element in each list? I do not know why it appears and how to fix it. Any ideas?
A list is a data type that has two type of functors/constants:
the empty list [] which has no arguments; and
the "cons" [element|list].
As is denoted in the second option, the second parameter of a cons should be a list. This can be another cons (and thus recursively further), or an empty list. Nevertheless, Prolog is not really typed, so you can use an integer, character,... as second item, but then it is not a list.
So now the question is, "how do we construct such weird list". In this answer, I used a smaller example to reproduce the error, because it makes things easier:
?- trace.
true.
[trace] ?- pack([1,1], X).
Call: (7) pack([1, 1], _G1066) ? creep
Call: (8) 1\=1 ? creep
Fail: (8) 1\=1 ? creep
Redo: (7) pack([1, 1], _G1066) ? creep
Call: (8) pack([1], [_G1144|_G1141]) ? creep
Exit: (8) pack([1], [1]) ? creep
Exit: (7) pack([1, 1], [[1|1]]) ? creep
X = [[1|1]] .
If we thus pack two elements, something goes wrong. First we call pack([1,1],X).
First the third clause fires, but the H \= T item fails. So as a result Prolog redoes the call, but now with the last clause. In the last clause, we see something weird:
pack([H, H|HS], [[H|TFR]|TR]):-
pack([H|HS], [TFR|TR]).
What we see is that we perform a recursive call on pack/2 with [TFR|TR]. So that means [TFR|TR] should be a list of lists. But the second clause does not generate a list of lists, but only a list of items. So the error is in:
pack([X], [X]).
%% ^ list of items??
So what we need to do to resolve the error, is rewrite the second clause to:
pack([X], [[X]]).
%% ^ list of list
Now we have solved that problem, but we are still not there yet: there is also an type error in the third clause:
pack([H, T|TS], [H|TR]):-
%% ^ item instead of a list?
H \= T,
pack([T|TS], TR).
Again we can simply make it a list of items:
pack([H, T|TS], [[H]|TR]):-
%% ^ list
H \= T,
pack([T|TS], TR).
And now we obtain the following code:
pack([], []).
pack([X], [[X]]).
pack([H, T|TS], [[H]|TR]):-
H \= T,
pack([T|TS], TR).
pack([H, H|HS], [[H|TFR]|TR]):-
pack([H|HS], [TFR|TR]).
We then obtain:
?- pack([1,1,1,1,2,3,3,1,1,4,5,5,5,5], X).
X = [[1, 1, 1, 1], [2], [3, 3], [1, 1], [4], [5, 5, 5|...]] [write]
X = [[1, 1, 1, 1], [2], [3, 3], [1, 1], [4], [5, 5, 5, 5]] .
EDIT:
In case there is only one element, you apparently do not want to construct a list. That makes the problem a bit harder. There are two options:
we adapt the code such that if such element occurs, we do not add it to a list; or
we perform some post processing, where we "unlist" lists with one element.
The last one is quite trivial, so lets do the first one. In that case, the second clause should indeed read:
pack([X],[X]).
Now the second clause should read:
pack([H, T|TS], [H|TR]):-
H \= T,
pack([T|TS], TR).
as well. But the last clause, is harder:
pack([H, H|HS], [[H|TFR]|TR]):-
pack([H|HS], [TFR|TR]).
There are two possibilities here:
TFR is a list of items, in that case we simply prepend to the list; or
TFR is not a list, in which case we construct a list.
In order to solve this problem, we can define a predicate:
prepend_list(H,[HH|T],[H,HH|T]).
prepend_list(H,X,[H,X]) :-
X \= [_|_].
and then use:
pack([H, H|HS], [HTFR|TR]):-
pack([H|HS], [TFR|TR]),
prepend_list(H,TFR,HTFR).
So now we obtain:
pack([], []).
pack([X], [X]).
pack([H, T|TS], [H|TR]):-
H \= T,
pack([T|TS], TR).
pack([H, H|HS], [HTFR|TR]):-
pack([H|HS], [TFR|TR]),
prepend_list(H,TFR,HTFR).
prepend_list(H,[HH|T],[H,HH|T]).
prepend_list(H,X,[H,X]) :-
X \= [_|_].
Note however that this program will fail if you want to pack/2 lists itself. In that case you better use a post processing step anyway.
Now it constructs:
?- pack([1,1,1,1,2,3,3,1,1,4,5,5,5,5], X).
X = [[1, 1, 1, 1], 2, [3, 3], [1, 1], 4, [5, 5, 5|...]] [write]
X = [[1, 1, 1, 1], 2, [3, 3], [1, 1], 4, [5, 5, 5, 5]] .

Why is this row in prolog returning false?

I am trying to write a Prolog code, but I can't get this to return true. I am trying to find a list, which all elements are included in two other lists. For example all list A elements are found in B and C lists each, not together.
My Prolog code is :
member(X, [X|_]).
member(X, [_|T]) :-
member(X, T).
first([H0|T0], [H0|T1], A) :-
member(H0, A),
first(T0, [H0|T1], A).
first([H0|T0], [_|T1], A) :-
first([H0|T0], T1, A).
where member predicate returns true if an element is in a list. With predicate 'first' I am trying to use member predicate to find a matching element of A and B in C list. If I find, then go further in the first list and compare its first element to second lists elements and again, if I would matching, I check with if I can find it in third list. I hope it does this, but when I run
?- first([4, 6, 4], [4, 5, 6, 4], [1, 2, 4, 6]).
it gives false and I can't figure out why. This seems as a simple attention mistake somewhere, but I just can't get my head around it.
I don't know anything about prolog, but like everyone I've been bitten by logic errors before. (=
As I have commented, you seem to lack a base case for first([], _, _). An example:
first([4], [4], [4]) :-
member(4, [4]), // quite true
first([], [4], [4]). // No matching rule, as all those assume an existing head in the first argument
I am not sure I understood your question, but allow me to try to specify further your predicate first/3:
first(+L, +L1, +L2)
succeeds if every element of L is found either in L1 or in L2.
If this is what you're looking for, then:
first([], _, _).
first([E|L], L1, L2) :-
(member(E, L1); member(E, L2)),
first(L, L1, L2).
Examples of success:
first([1, 2, 3], [1, 2, 3], [1, 2]).
first([1], [1, 2, 3], [1, 2]).
first([1, 2, 3], [1, 2, 3], []).
Examples of faiure:
first([1, 2, 3, 5], [1, 2, 3], [1, 2]).
first([7], [1, 2, 3], [1, 2]).
first([1, 2, 3], [], []).

PROLOG: Keep list in recursion

So, I've spent a lot of my time trying to figure this out without almost no progress. Hope you could help me.
The goal is, to take a list like this(lets call it baselist): [[[feesc,11],[podshare,11]],[[feesc,11]],[]]. And make it become this: [[feesc,22],[podshare,11]].
I have a predicate responsible to add or sum to the resulting list. Here is the code:
place_key([Key,Value], [], [Key,Value]).
place_key([Key,Value], [[Key,V]|Rest], [[Key,V1]|Rest]) :- V1 is V+Value.
place_key([Key,Value], [[K,V]|Rest], [[K,V]|List2]) :- Key \= K, place_key([Key,Value], Rest, List2)."
If I manually call this method, for simulating the recursion, it works exactly how I want.
Example:
place_key([feesc,11], [], R), place_key([feesc,11],R,J).
So J is = [[feesc,22]].
Expected result is correct.
The problem is to that with recursion.
So basically what I need to do is: iterate through the baselist, when reaching each key/par list, call place_key and keep it in the stack so the recursion keeps it until the last.
Just to point out, I don't want to append, I just need the latest result from place_key.
What I have done so far:
fe([HO|T],NL,R) :- write(HO), place_key(HO,NL,RESULT), fe(T,RESULT,R).
fe(S,R):- fe(S,[],R).
fe([],[]).
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
When I run:
[trace] 57 ?- feg([[[feesc,11]],[[feesc,11]]],R).
Call: (6) feg([[[feesc, 11]], [[feesc, 11]]], _G21384) ? creep
Call: (7) fe([[feesc, 11]], _G21484) ? creep
Call: (8) fe([[feesc, 11]], [], _G21485) ? creep
Call: (9) place_key([feesc, 11], [], _G21485) ? creep
Exit: (9) place_key([feesc, 11], [], [[feesc, 11]]) ? creep //Until here, I think this is correct.
Call: (9) fe([], [[feesc, 11]], _G21494) ? creep
Fail: (9) fe([], [[feesc, 11]], _G21494) ? creep
Redo: (9) place_key([feesc, 11], [], _G21485) ? creep
Fail: (9) place_key([feesc, 11], [], _G21485) ? creep
Fail: (8) fe([[feesc, 11]], [], _G21485) ? creep
Fail: (7) fe([[feesc, 11]], _G21484) ? creep
Fail: (6) feg([[[feesc, 11]], [[feesc, 11]]], _G21384) ? creep
false.
What am I doing wrong?
The problem in your case is that you don't define a base-case for fe/3. As you can see, except for your place_key predicate, you also have the following:
fe([HO|T],NL,R) :- write(HO), place_key(HO,NL,RESULT), fe(T,RESULT,R).
fe(S,R):- fe(S,[],R).
fe([],[]).
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
I'll try to make this a little more readable, so you can see what's going on:
% fe/3 cases
fe([Head|Tail],Current,Result) :- write(Head), place_key(Head,Current,TempResult), fe(Tail,TempResult,Result).
% fe/2 cases
fe(S,R):- fe(S,[],R).
fe([],[]).
%% this case above is never used, as the first case always matches
% recursive and base cases for feg
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
You should rewrite this as following:
fe([],Result,Result).
This is your base case, if the list is empty, the result in-between is equal to the final result. Prolog always tries the first possible match first, so always set your base-case on top.
fe([Head|Tail],Current,Result) :- write(Head), place_key(Head,Current,TempResult), fe(Tail,TempResult,Result).
This is your recursive case, as you had before, which we will put below our base case.
We can drop the second fe/2 case, as the first case always matches and we rewrite to fe/3 anyway, which can handle all cases.
fe(S,R):- fe(S,[],R).
Below are your existing feg/2 cases. Here is also an error, because after your first fe/2-predicate, the RESULT-variable has a value, but it still needs to be able to unify with the call feq(T,RESULT), which will produce a different value. I'll leave this as an exercise.
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
Keep your key/pairs as a tuple, a simple term with an arity of 2. Something like K-V or K:V or even tuple(K,V) is preferable to [K,V]. There's a simple reason for this:
K-V, K:V and tuple(K,V) all map to simple structures: -(K,V), :(K,V) and tuple(K,V) respectively, while...
[K,V] is syntactic sugar for a rather more complicated structure .(K,.(V,[])).
Further, you might realize that your key/value pairs are hard to distinguish from the nested list-of-lists. Keeping the Key/Value pairs as tuples makes that distincation clear.
So, let us assume your key/value pairs are represented as K:V. It sounds to me that what you're essentially wanting to do is walk your nested list-of-lists (essentially, a tree), enumerate the key/value pairs it contains and produce the set (unique). Here's one way to do that.
First, a simple predicate to identify a non-empty list:
nonnempty_list( L ) :- nonvar(L) , L = [_|_] .
Then, a simple predicate to walk the nested list of lists and enumerate each key/value pair it finds:
visit( [ K:R | Ls ] , K:R ) . % succeed if the head of the list is a key/value pair.
visit( [ L | Ls ] , KVP ) :- % otherwise...
nonempty_list(L) , % - if the head is a non-empty list ,
visit( L , KVP ) % - visit it.
. %
visit( [_|Ls] , KVP ) :- % finally...
visit( Ls , KVP ) % - recurse down on the tail.
. %
Then you can use the magic of setof/3 to get what you want:
flattened_set( LoL , KVPs ) :-
setof( KVP , visit(LoL,KVP) , KVPs )
.

How Does Prolog print out 2 lists as one list, without any append code?

I have the following code, which is apparently the standard way to show the union between 2 lists:
union([Head|Tail],List2,Result) :-
member(Head,List2), union(Tail,List2,Result).
union([Head|Tail],List2,[Head|Result]) :-
\+ member(Head,List2), union(Tail,List2,Result).
union([],List2,List2).
and on the following input:
union([a,b,c,d,2,3], [b,c,3,99], Result).
will give me the following output:
Result = [a,d,2,b,c,3,99] ?
yes
My question is, How does prolog do this? List2 is never changed throught the recursive calls, but at the end, it prints out all elements that make the union between the 2 original lists.
Please help me understand this code.
Thank you.
let's assume that you ask union([1,2],[2],R).
according to the first rule, union([1|[2]],[2],R) would be true if
member(1,[2]) --> false
then prolog will check the second rule union([1|[2]],[2],[1|R]) will be true if
+member(1,[2]) --> true
and union([2],[2],R)
now, union([2|[]],[2],R) would be true (1st rule) if
member(2,[2]) -->true
and union([],[2],R)
union([],[2],R) would be true (3rd rule) if R=[2]
so R=[2] and therefore the first call to union returns [1|[2]] = [1,2]
a useful tool to find out "how prolog does it" is trace/0:
2 ?- trace.
true.
[trace] 2 ?- union([1,2],[2],R).
Call: (6) union([1, 2], [2], _G543) ? creep
Call: (7) lists:member(1, [2]) ? creep
Fail: (7) lists:member(1, [2]) ? creep
Redo: (6) union([1, 2], [2], _G543) ? creep
Call: (7) lists:member(1, [2]) ? creep
Fail: (7) lists:member(1, [2]) ? creep
Call: (7) union([2], [2], _G619) ? creep
Call: (8) lists:member(2, [2]) ? creep
Exit: (8) lists:member(2, [2]) ? creep
Call: (8) union([], [2], _G619) ? creep
Exit: (8) union([], [2], [2]) ? creep
Exit: (7) union([2], [2], [2]) ? creep
Exit: (6) union([1, 2], [2], [1, 2]) ? creep
R = [1, 2] .
all in all: List2 doesnt not change but the predicate does not return List2 either; it returns a list created by List2 and the unique elements of List1
The algorithm in work here is the following :
1) initialize the result to List2. This part is implemented thanks to :
union([], List2, List2).
2) go through List1 and do the following for each item :
2a) add it to Result if the item is not in List2. That part is implemented thanks to this clause :
union([Head|Tail], List2, [Head|Result]) :-
\+ member(Head, List2),
union(Tail, List2, Result).
2b) don't do anything if the item is in List2. That part is implemented thanks to this clause :
union([Head|Tail], List2, Result) :-
member(Head, List2),
union(Tail, List2, Result).
For step by step comprehension of the prolog execution, please refer to #thanosQR answer.
By the way, note that this predicate needs sets to return a good union, else, a duplicate in List1 will stay a duplicate in Result (so will a duplicate in List2).
That code it's actually rather inefficient, so we can't assume it as the 'standard way' to compute union. At first glance, there are 2 simple optimizations: avoid repeat the membership test, and use memberchk/2 instead of member/2. So we can rewrite it in the following way:
union([Head|Tail], List2, ResultT) :-
( memberchk(Head, List2)
-> ResultT = Result
; ResultT = [Head|Result] ),
union(Tail, List2, Result).
union([],List2,List2).
The difference in performance is huge. With relatively small lists:
...
numlist(1, 10000, A),
numlist(5000, 10000, B),
union(A, B, C),
...
we pass from 62,532,499 inferences to 20,002 inferences, and the test doesn't force the evaluation of all alternatives (backtrack points from member): adding this we need 25,015,004 more inferences, albeit no more solution is available. Here the code from SWI-Prolog lists library:
%% union(+Set1, +Set2, -Set3) is det.
%
% True if Set3 unifies with the union of Set1 and Set2.
% The complexity of this predicate is |Set1|*|Set2|
%
% #see ord_union/3.
union([], L, L) :- !.
union([H|T], L, R) :-
memberchk(H, L), !,
union(T, L, R).
union([H|T], L, [H|R]) :-
union(T, L, R).
It's similar to your version, please note the cut (!)

Prolog permutation extracting solutions

permutation([], []).
permutation(L, [X|Xs]) :- select(X, L, Rest), permutation(Rest, Xs).
If I type permutation([1,2,3],R), the first solution is "[1,2,3]" but how to get to the second one without using ";" or "fail". I need to use the 2nd solution like "[1,3,2]" or so in order compare it to another list.
What I mean is:
permutation([], []).
permutation(L, [X|Xs]) :- select(X, L, Rest), permutation(Rest, Xs).
go_perm(L,P) :-
L = P,
write(P),nl.
go_perm(L,P) :-
permutation(P,P2), % in this case i wanna get the next solution -.-
go_perm(L,P2).
If L = P then it finishes. Permutation of the first solution for "[1,2,3]" is "[1,2,3]". But that pulls me into stackoverflow because it runs into never-endless thing.
Perhaps you understand me. Thanks!
Assuming you want to loop over the solutions to print them
One standard way to accomplish this is to fail and backtrack, as in:
print_all_permutations(X)
:- permutation(X, Y), print(Y), nl, fail ; true.
Assuming you just want to check if a given solution is correct
You are already done. Just call the function with the reference list and the list you want to test:
permutation([1, 2, 3], [2, 1, 3]).
will return true, because [2, 1, 3] is a permutation of [1, 2, 3]. If the second argument is not a permutation, the goal will evaluate to false.
This is the magic of prolog: finding a solution, or checking if a given solution is correct, are the same thing.
In between: partial solution
The same reasoning still applies:
permutation([1, 2, 3], [2, X, 3]).
will display the only possible value for X.
Or, if you want the whole list to be the result:
X = [2, X, 3], permutation([1, 2, 3], X).
You need to look at various aggregate predicates. Here, findall would work nicely. you can invoke it:
ListIn=[1,2,3], findall(Perm, permutation(ListIn, Perm), Permutations).
This will call permutation on ListIn until it fails. Each Perm returned by permutation will be collected into the Permutations variable.
permutation is a predicate that succeeds when one list is a permutation of the other. You don't actually need to enumerate them; just write permutation([1, 2, 3], [2, 1, 3]) and Prolog will tell you "true".