Even sized list in Prolog - list

I've been trying to write a predicate which would evaluate the size of a list to be even or not and this has to be done without computing the length of the list or any arithmetic operations. It's supposedly easier than computing the length but I'm having trouble thinking of how to do it without that. I'm guessing a sort of recursive technique but if anyone is able to help it would be great.

Yes, you want recursion. The base cases would be the smallest odd/even lists you can have, and then all you need is to figure out how to construct the recursive call so that it will boil down to the base case. You could start out by imagining a list of length 3 that's supposed to return true for "oddList". If it's not the base case, what's the next logical step? How does an odd list differ from an even one?

Preserve logical-purity! Simply proceed like this:
evenlength([]). % smallest list with even length is [] (length=0)
evenlength([_|Xs]) :-
oddlength(Xs).
oddlength([_|Xs]) :- % smallest list with odd length is [_] (length=1)
evenlength(Xs).
Some simple ground queries for evenlength/1 and oddlength/1:
?- evenlength([]).
true.
?- oddlength([]).
false.
?- evenlength([1]).
false.
?- oddlength([1]).
true.
?- evenlength([1,2]).
true.
?- oddlength([1,2]).
false.
?- evenlength([1,2,3]).
false.
?- oddlength([1,2,3]).
true.
Note that these predicates can not only test candidate lists, but also generate them:
?- evenlength(Xs).
Xs = []
; Xs = [_A,_B]
; Xs = [_A,_B,_C,_D]
; Xs = [_A,_B,_C,_D,_E,_F]
...
?- oddlength(Xs).
Xs = [_A]
; Xs = [_A,_B,_C]
; Xs = [_A,_B,_C,_D,_E]
; Xs = [_A,_B,_C,_D,_E,_F,_G]
...

Using meta-predicate foldl/4 and Prolog lambdas all we need to do is:
evenlength(Xs) :-
foldl(\_^E^O^(O is \E),Xs,1,1). % each item in `Xs` flips the "evenness flag"
Sample uses:
?- evenlength([]).
true.
?- evenlength([_]).
false.
?- evenlength([_,_]).
true.
?- evenlength([_,_,_]).
false.
?- evenlength([_,_,_,_]).
true.
Let's not forget about the most general query!
?- evenlength(Xs).
Xs = []
; Xs = [_A,_B]
; Xs = [_A,_B,_C,_D]
; Xs = [_A,_B,_C,_D,_E,_F]
...

I know it is too late to answer your question, but hopefully this will help:
To find list has odd length:
oddlength([_]).
oddlength([_,_|R]) :- oddlength(R),!.
To find list has even length:
evenlength([]).
evenlength([_,_|R]) :- evenlength(R),!.

Related

Prolog Convert a list in a list of lists

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]].

Palindrome (homework)

I tried to write a Prolog program by using lists. However, I have to use difference lists and output should be:
The ith element of the list is the same of (n-i+1)th element of the list and n is the length of the list. For example, [a,X,c,b,Y] should give X = b and Y = a. I could not find similar palindrome example in other questions.
So far I have implemented:
% length of the list
len([], 0).
len([H|T], B) :-
len(T, NT),
B is NT + 1.
% return the ith element of the list
match([H|_], 0, H) :-
!.
match([_|T], N, H) :-
N > 0,
N1 is N-1,
match(T, N1, H).
However, I could not complete. Please help me!
Use definite clause grammars!
DCG, a major Prolog feature, makes using difference lists easy—enabling you to write concise and efficient code with little effort!
Want to know more? Just follow the dots:
DCG has its own tag on StackOverflow, dcg.
en.wikipedia.org has an extensive article on DCG.
For a jumpstart, read the DCG primer by Markus Triska!
Without any further ado, let's get to the code:
palindrome --> [].
palindrome --> [_].
palindrome --> [X], palindrome, [X].
% Alternatively, we could also use the following more compact definition:
palindrome --> [] | [_] | [X], palindrome, [X].
Done. Let's run a few queries! First, the query the OP gave:
?- phrase(palindrome, [a,X,c,b,Y]).
X = b, Y = a
; false.
In German, "corn" is called "mais". If we put "siam" (the old name of "the Kingdom of Thailand") in front, we get a delicious palindrome:
?- set_prolog_flag(double_quotes, chars).
true.
?- phrase(palindrome, "siammais").
true
; false.
?- phrase(palindrome, "siamais"). % or kick one middle 'm' character
true % ... for an odd-length palindrome
; false.
At last, let's not forget about the most general query:
?- phrase(palindrome, Xs).
Xs = []
; Xs = [_A]
; Xs = [_A,_A]
; Xs = [_A,_B,_A]
; Xs = [_A,_B,_B,_A]
; Xs = [_A,_B,_C,_B,_A]
...
On the prolog-toplevel we can use the built-in Prolog predicate listing/1 to peek at the code the DCG was "translated" to—at this level the internal use of difference-lists becomes apparent:
?- listing(palindrome//0).
palindrome(A, A).
palindrome([_|A], A).
palindrome([C|A], D) :-
palindrome(A, B),
B = [C|D].
true.

How can I compare two lists in prolog, returning true if the second list is made of every other element of list one?

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].

Repeated elements in a list in Prolog

I would like to find a method to find the most repeated element in a list if two elements repeat the same number of times. I want the predicate to be a list that contains both elements. How can I do that?
Sample queries and expected answers:
?- maxRepeated([1,3,3,4,2,2],X).
X = [3,2].
% common case: there is one element that is the most repeated
?- maxRepeated([1,3,3,3,3,4,2,2],X).
X = [3].
% all elements repeat the same number of times
?- maxRepeated([1,3,4,2],X).
X = [1,3,4,2].
I have the same problem with the less repeated element.
The predicate mostcommonitems_in/2 (to be presented in this answer) bears more than a little resemblance to
mostcommonitem_in/2, defined in one of my previous answers.
In the following we use list_counts/2, Prolog lambdas, foldl/4, tchoose/3, and (=)/3:
:- use_module(library(lambda)).
mostcommonitems_in(Ms,Xs) :-
list_counts(Xs,Cs),
foldl(\ (_-N)^M0^M1^(M1 is max(M0,N)),Cs,0,M),
tchoose(\ (E-N)^E^(N=M), Cs,Ms).
Let's run some queries!
First, the three queries given by the OP:
?- mostcommonitems_in(Xs,[1,3,3,4,2,2]).
Xs = [3,2].
?- mostcommonitems_in(Xs,[1,3,3,3,3,4,2,2]).
Xs = [3].
?- mostcommonitems_in(Xs,[1,3,4,2]).
Xs = [1,3,4,2].
Alright! Some more ground queries---hat tip to #lurker and #rpax:
?- mostcommonitems_in(Xs,[1,3,2,1,3,3,1,4,1]).
Xs = [1].
?- mostcommonitems_in(Xs,[1,3,3,4,3,2]).
Xs = [3].
?- mostcommonitems_in(Xs,[1,2,3,4,5,6]).
Xs = [1,2,3,4,5,6].
?- mostcommonitems_in(Xs,[1,3,3,4,2,3,2,2]).
Xs = [3,2].
OK! How about three items each of which occurs exactly three times in the list?
?- mostcommonitems_in(Xs,[a,b,c,a,b,c,a,b,c,x,d,e]).
Xs = [a,b,c]. % works as expected
How about the following somewhat more general query?
?- mostcommonitems_in(Xs,[A,B,C]).
Xs = [C] , A=B , B=C
; Xs = [B] , A=B , dif(B,C)
; Xs = [C] , A=C , dif(B,C)
; Xs = [C] , dif(A,C), B=C
; Xs = [A,B,C], dif(A,B), dif(A,C), dif(B,C).
Above query breaks almost all impure codes... Our Prolog code is pure, so we're good to go!
I don't know too much about prolog, and probably there's a way to do this better, but here's a working solution: (SWI prolog)
%List of tuples, keeps track of the number of repetitions.
modify([],X,[(X,1)]).
modify([(X,Y)|Xs],X,[(X,K)|Xs]):- K is Y+1.
modify([(Z,Y)|Xs],X,[(Z,Y)|K]):- Z =\= X, modify(Xs,X,K).
highest((X1,Y1),(_,Y2),(X1,Y1)):- Y1 >= Y2.
highest((_,Y1),(X2,Y2),(X2,Y2)):- Y2 > Y1.
maxR([X],X).
maxR([X|Xs],K):- maxR(Xs,Z),highest(X,Z,K).
rep([],R,R).
rep([X|Xs],R,R1):-modify(R,X,R2),rep(Xs,R2,R1).
maxRepeated(X,R):- rep(X,[],K),maxR(K,R).
?- maxRepeated([1,3,3,4,3,2] ,X).
X = (3, 3) .
?- maxRepeated([1,2,3,4,5,6] ,X).
X = (1, 1) .
The less repeated element is analogous.
I think that is better to use tuples in this case, but changing the result into a list shouldn't be a problem.
There is my solution on Visual Prolog:
domains
value=integer
tuple=t(value,integer)
list=value*
tuples=tuple*
predicates
modify(tuples,value,tuples)
highest(tuple,tuple,tuple)
maxR(tuples,integer,integer)
maxR(tuples,integer)
rep(list,tuples,tuples)
maxRepeated(list,list)
filter(tuples,integer,list)
clauses
modify([],X,[t(X,1)]):- !.
modify([t(X,Y)|Xs],X,[t(X,K)|Xs]):- K = Y+1, !.
modify([t(Z,Y)|Xs],X,[t(Z,Y)|K]):- Z <> X, modify(Xs,X,K).
highest(t(X1,Y1),t(_,Y2),t(X1,Y1)):- Y1 >= Y2, !.
highest(t(_,Y1),t(X2,Y2),t(X2,Y2)):- Y2 > Y1.
maxR([],R,R):- !.
maxR([t(_,K)|Xs],Rs,R):- K>Rs,!, maxR(Xs,K,R).
maxR([_|Xs],Rs,R):- maxR(Xs,Rs,R).
maxR(X,R):- maxR(X,0,R).
rep([],R,R).
rep([X|Xs],R,R1):-modify(R,X,R2),rep(Xs,R2,R1).
filter([],_,[]):-!.
filter([t(X,K)|Xs],K,[X|FXs]):- !, filter(Xs,K,FXs).
filter([_|Xs],K,FXs):- filter(Xs,K,FXs).
maxRepeated(X,RL):- rep(X,[],Reps),maxR(Reps,K),filter(Reps,K,RL).
goal
maxRepeated([1,3,3,4,2,3,2,2] ,X),
maxRepeated([1,2,3,4,5,6] ,Y).

Prolog how to swap two by two elements in a list function?

I need a function in Prolog: swapcouple(L, L1).
swapcouple([a,b,c,d,e], M) --> output M=[b,a,d,c,e]
swapcouple([a,b,c,d], M) --> output M=[b,a,d,c]
(what have you tried?) This is a valid definition:
swapcouple([a,b,c,d,e], M) :- M=[b,a,d,c,e].
swapcouple([a,b,c,d], M) :- M=[b,a,d,c].
Proceed by abstraction. For example,
swapcouple([A,B,C,D,E], M) :- M=[B,A,D,C,E].
swapcouple([A,B,C,D], M) :- M=[B,A,D,C].
Do you see where I'm going? [A,B,C,D,E] = [A,B | R] where R = [C,D,E]. Can we use that?
swapcouple([A,B|R], M) :- R=[C,D,E], M=[B,A|S], S=[D,C,E].
Right? Here's the crucial bit. R=[C,D,E], S=[D,C,E] is the same as swapcouple(R,S), isn't it?
swapcouple([A,B|R], M) :- M=[B,A|S], swapcouple(R,S).
Assuming that swapcouple does what it is advertised to do, we can just use it when the need arises. Here you've got your very own recursive procedure (well, predicate). It is even tail recursive modulo cons, which is even more hip and fun.
Few more edge cases are missing there. I'm positive you can finish it up.
The implementation can hardly get more direct than this:
list_swappedcouples([],[]).
list_swappedcouples([A],[A]).
list_swappedcouples([A,B|Xs],[B,A|Ys]) :-
list_swappedcouples(Xs,Ys).
Here are your sample queries:
?- list_swappedcouples([a,b,c,d,e],Ls).
Ls = [b,a,d,c,e] ; % succeeds, but leaves behind choicepoint
false.
?- list_swappedcouples([a,b,c,d],Ls).
Ls = [b,a,d,c]. % succeeds deterministically
Edit 2015-06-03
We can utilize first argument indexing to improve determinism.
list_with_swapped_couples([],[]).
list_with_swapped_couples([X|Xs],Ys) :-
list_prev_w_swapped_couples(Xs,X,Ys).
list_prev_w_swapped_couples([],X,[X]).
list_prev_w_swapped_couples([X1|Xs],X0,[X1,X0|Ys]) :-
list_with_swapped_couples(Xs,Ys).
Note that all following sample queries succeed deterministically.
?- list_with_swapped_couples([],Xs).
Xs = [].
?- list_with_swapped_couples([1],Xs).
Xs = [1].
?- list_with_swapped_couples([1,2],Xs).
Xs = [2,1].
?- list_with_swapped_couples([1,2,3],Xs).
Xs = [2,1,3].
?- list_with_swapped_couples([1,2,3,4],Xs).
Xs = [2,1,4,3].
?- list_with_swapped_couples([1,2,3,4,5],Xs).
Xs = [2,1,4,3,5].