list of ordered pairs in prolog - list

I am trying to implement a prolog method that will take a number and return a list of all possible ordered pairs where both X and Y are less than the number given. For example
genXY(2,R).
Should return
R=[0,0];
R=[0,1];
R=[1,0];
R=[1,1].
I am having trouble understanding how to implement this. I have written the code
genN(N,R) :-
N1 is N-1,
between(0,N1,R).
Which will give the following output when executed
genN(3,R).
R=0;
R=1;
R=2;
And I believe that I should use forall to implement genXY but I don't understand how I would go about doing this

Just use between/3 twice:
?- N = 2, R = X-Y, succ(N0, N), between(0, N0, X), between(0, N0, Y).
R = 0-0;
R = 0-1;
R = 1-0;
R = 1-1;

Related

PROLOG sum of integers inside a list

I have a list of functions
List = [segmentTime(red,a,c,2),segmentTime(green,c,e,3),segmentTime(green,e,h,4),segmentTime(blue,h,i,5)]
How do I find the sum of the integer part of the function of all elements in the list?
i.e
sum = 2+3+4+5
A snippet code of a predicate would be extremely useful.
Thanks in advance :)
You will be surprised how simple the answer is.
sumList([],0).
sumList([segmentTime(_,_,_,X)|T],Z):- sumList(T,Z1),Z is Z1+X.
OUTPUT
?-sumList([segmentTime(red,a,c,2),segmentTime(green,c,e,3),segmentTime(green,e,h,4),segmentTime(blue,h,i,5)],M).
M=14
Hope this helped you.
Another way is to use library(lambda).
:- use_module(library(lambda)).
getList(L):-
L = [segmentTime(red,a,c,2),segmentTime(green,c,e,3),segmentTime(green,e,h,4),segmentTime(blue,h,i,5)].
sumOfList(L, S) :-
foldl(\X^Y^Z^(X = segmentTime(_,_,_,V), Z is Y + V), L, 0, S).
Ouput :
?- getList(L), sumOfList(L, S).
L = [segmentTime(red, a, c, 2), segmentTime(green, c, e, 3), segmentTime(green, e, h, 4), segmentTime(blue, h, i, 5)],
S = 14.

How to simplify algebra equations represented as list of list

With Prolog I want to simplify algebra expression represented as as list of list:
algebra equation
f = 3x+2
list of list
[[3,1],[2,0]]
3 and 2 are coefficients
1 and 0 are exponents
That should be obvious.
I am looking for some tips or suggestions on how to code the simplifications for this example:
f = 3x+2x+1+2
[[3,1],[2,1],[1,0],[2,0]]
simplified:
f = 5x+3
[[5,1],[3,0]]
I have tried some built in functions but did not get the proper idea about how to use them.
One liner, similar to what's proposed by joel76:
simplify(I,O) :-
bagof([S,E],L^(bagof(C,member([C,E],I),L),sum_list(L,S)),O).
The inner bagof collects C (coefficients) given E (exponents), the resulting list L is summed into S, and paired with E becomes [S,E], an element (monomial) of O.
If you omit the universal quantification specifier (that is L^) you get single monomials on backtracking.
You can solve your problem in this way:
simplify(_,_,S,S,[]):- !.
simplify(L,I,Sum,NTot,[[I,S]|T]):-
Sum =< NTot,
findall(X,member([X,I],L),LO),
length(LO,N),
S1 is Sum + N,
sum_list(LO,S),
I1 is I+1,
simplify(L,I1,S1,NTot,T).
write_function([]).
write_function([[D,V]|T]):-
write(' + '),write(V),write('x^'),write(D),
write_function(T).
test:-
L = [[3,1],[2,1],[1,0],[2,0]],
length(L,N),
simplify(L,0,0,N,LO),
LO = [[D,V]|T],
write('f='),write(V),write('x^'),write(D),
write_function(T).
The main predicate is simplify/5 which uses findall/3 to find all the coefficients with the same degree and then sums them using sum_list/2. Then you can write the result in a fancy way using write_function/1.
In SWI-Prolog You can use aggregate :
pred(>, [_,X], [_,Y]) :- X > Y.
pred(<, [_,X], [_,Y]) :- X < Y.
pred(=, [_,X], [_,X]).
simplify(In, Out) :-
aggregate(set([S,X]), aggregate(sum(P), member([P,X], In), S), Temp),
predsort(pred, Temp, Out).
For example :
?- simplify([[3,1],[2,1],[1,0],[2,0]], Out).
Out = [[5, 1], [3, 0]] ;
false.

Give as a solution every different number in a list of lists

I need to do a predicate, select(ListOfLists, X) that returns as a solution every different number in a list of lists, starting with the numbers that are alone in a list, for example:
select([[1,2,3],[1,2],[4],[3]],X).
Would return:
X = 4 ;
X = 3 ;
X = 2 ;
X = 1
Order doesn't matter as long as the numbers that are alone in the list are shown first.
To do this, first I coded 2 other predicates, which are:
%OrderedList is Lists ordered by size.
orderListsBySize(Lists, OrderedLists).
Example: orderListsBySize([[1,2],[6],[3,4,5]], L). ->L = [[6], [1,2], [3,4,5]]
And
%ListsWithoutX is Lists without the X elements
removeFromLists(X, Lists, ListsWithoutX).
Example: removeFromLists(1,[[1,2],[3],[4,1,5]],L). -> L = [[2],[3],[4,5]]
Both predicates work.
Then, to do the select(ListOfLists, X) predicate, I tried the following:
select([[X|[]]|_], X). select(L1,S) :-
orderListsBySize(L1, [[X|XS]|LS]),
length(XS, A),
A == 0,
select([[X|[]]|M], S),
removeFromLists(X, [XS|LS], M).
select([[X|_]|_], X).
But it doesn't work.
It's not a hard exercise to do in other languages, the problem is that it's still hard for me to understand how prolog works. I appreaciate any help, thanks!
You could start with:
select2(ListOfLists,Element):-
length(List,_Len),
member(List,ListOfLists),
member(Element,List).
Which will return all the answers, but then get stuck in a loop looking for ever bigger lists.
This can be averted using the :-use_module(library(clpfd)). and defining a fd_length/2 which wont keep looking for bigger lists then exist in the list of lists.
fd_length(L, N) :-
N #>= 0,
fd_length(L, N, 0).
fd_length([], N, N0) :-
N #= N0.
fd_length([_|L], N, N0) :-
N1 is N0+1,
N #>= N1,
fd_length(L, N, N1).
select(ListOfLists,Element):-
maplist(length,ListOfLists,Lengths),
sort(Lengths,SortedLength),
last(SortedLength,Biggest),
Biggest #>= Len,
fd_length(List,Len),
member(List,ListOfLists),
member(Element,List).
Example Query:
?-select([[1,2,3],[1,2],[4],[3]],X).
X = 4
X = 3
X = 1
X = 2
X = 1
X = 2
X = 3
false
If you want unique solutions, you could enclose in a setof/3 and then call member/2 again.

How to move first N elements to the end of the list

I am wondering how can I move first N elements from a list and put them at the end.
For example:
[1,2,3,4] and I want to move first 2 elements , so the result will be [3,4,1,2].
rule(List1,N,List2) :- length(List1,Y), ...
I don't know how to start, any advice ?
Since we are speaking of predicates - i.e. true relations among arguments - and Prolog library builtins are written with efficiency and generality in mind, you should know that - for instance - length/2 can generate a list, as well as 'measuring' its length, and append/3 can also split a list in two. Then, your task could be
'move first N elements to the end of the list'(L,N,R) :-
length(-,-),
append(-,-,-),
append(-,-,-).
Replace each dash with an appropriate variable, and you'll get
?- 'move first N elements to the end of the list'([1,2,3,4],2,R).
R = [3, 4, 1, 2].
You could opt to adopt a more general perspective on the task. If you think about it, taking the first N elements of a list and appending them at the end can be seen as a rotation to the left by N steps (just imagine the list elements arranged in a circle). The predicate name rotate/3 in #Willem Van Onsem's answer also indicates this perspective. You can actually define such a predicate as a true relation, that is making it work in all directions. Additionally it would be desirable to abstain from imposing unnecessary restrictions on the arguments while retaining nice termination properties. To reflect the relational nature of the predicate, let's choose a descriptive name. As the third argument is the left rotation by N steps of the list that is the first argument, let's maybe call it list_n_lrot/3 and define it like so:
:- use_module(library(lists)).
:- use_module(library(clpfd)).
list_n_lrot([],0,[]). % <- special case
list_n_lrot(L,N,LR) :-
list_list_samelength(L,LR,Len), % <- structural constraint
NMod #= N mod Len,
list_n_heads_tail(L,NMod,H,T),
append(T,H,LR).
list_list_samelength([],[],0).
list_list_samelength([_X|Xs],[_Y|Ys],N1) :-
N1 #> 0,
N0 #= N1-1,
list_list_samelength(Xs,Ys,N0).
list_n_heads_tail(L,N,H,T) :-
if_(N=0,(L=T,H=[]),
(N0#=N-1,L=[X|Xs],H=[X|Ys],list_n_heads_tail(Xs,N0,Ys,T))).
Now let's step through the definition and observe some of its effects by example. The first rule of list_n_lrot/3 is only included to deal with the special case of empty lists:
?- list_n_lrot([],N,R).
N = 0,
R = [] ;
false.
?- list_n_lrot(L,N,[]).
L = [],
N = 0 ;
false.
?- list_n_lrot(L,N,R).
L = R, R = [],
N = 0 ;
...
If you don't want to include these cases in your solution just omit that rule. Throughout the predicates CLP(FD) is used for arithmetic constraints, so the second argument of list_n_lrot/3 can be variable without leading to instantiation errors. The goal list_list_samelength/2 is a structural constraint to ensure the two lists are of same length. This helps avoiding an infinite loop after producing all answers in the case that only the third argument is ground (to see this, remove the first two goals of list_n_lrot/3 and replace the third with list_n_heads_tail(L,N,H,T) and then try the query ?- list_n_lrot(L,N,[1,2,3]).). It's also the reason why the most general query is listing the solutions in a fair order, that is producing all possibilities for every list length instead of only listing the rotation by 0 steps:
?- list_n_lrot(L,N,R).
... % <- first solutions
L = R, R = [_G2142, _G2145, _G2148], % <- length 3, rotation by 0 steps
N mod 3#=0 ;
L = [_G2502, _G2505, _G2508], % <- length 3, rotation by 1 step
R = [_G2505, _G2508, _G2502],
N mod 3#=1 ;
L = [_G2865, _G2868, _G2871], % <- length 3, rotation by 2 steps
R = [_G2871, _G2865, _G2868],
N mod 3#=2 ;
... % <- further solutions
Finally, it also describes the actual length of the two lists, which is used in the next goal to determine the remainder of N modulo the length of the list. Consider the following: If you rotate a list of length N by N steps you arrive at the initial list again. So a rotation by N+1 steps yields the same list as a rotation by 1 step. Algebraically speaking, this goal is exploiting the fact that congruence modulo N is partitioning the infinite set of integers into a finite number of residue classes. So for a list of length N it is sufficient to produce the N rotations that correspond to the N residue classes in order to cover all possible rotations (see the query above for N=3). On the other hand, a given N > list length can be easily computed by taking the smallest non-negative member of its residue class. For example, given a list with three elements, a rotation by 2 or 5 steps respectively yields the same result:
?- list_n_lrot([1,2,3],2,R).
R = [3, 1, 2].
?- list_n_lrot([1,2,3],5,R).
R = [3, 1, 2].
And of course you could also left rotate the list by a negative number of steps, that is rotating it in the other direction:
?- list_n_lrot([1,2,3],-1,R).
R = [3, 1, 2].
On a side note: Since this constitutes rotation to the right, you could easily define right rotation by simply writing:
list_n_rrot(L,N,R) :-
list_n_lrot(L,-N,R).
?- list_n_rrot([1,2,3],1,R).
R = [3, 1, 2].
The predicate list_n_heads_tail/4 is quite similar to splitAt/4 in Willem's post. However, due to the use of if_/3 the predicate succeeds deterministically (no need to hit ; after the only answer since no unnecessary choicepoints are left open), if one of the lists and the second argument of list_n_lrot/3 are ground:
?- list_n_lrot2([a,b,c,d,e],2,R).
R = [c, d, e, a, b].
?- list_n_lrot2(L,2,[c,d,e,a,b]).
L = [a, b, c, d, e].
You can observe another nice effect of using CLP(FD) with the second solution of the most general query:
?- list_n_lrot(L,N,R).
L = R, R = [],
N = 0 ;
L = R, R = [_G125], % <- here
N in inf..sup ; % <- here
...
This answer states, that for a list with one element any rotation by an arbitrary number of steps yields the very same list again. So in principle, this single general answer summarizes an infinite number of concrete answers. Furthermore, you can also ask questions like: What lists are there with regard to a rotation by 2 steps?
?- list_n_lrot2(L,2,R).
L = R, R = [_G19] ;
L = R, R = [_G19, _G54] ;
L = [_G19, _G54, _G22],
R = [_G22, _G19, _G54] ;
...
To finally come back to the example in your question:
?- list_n_lrot([1,2,3,4],2,R).
R = [3, 4, 1, 2].
Note how this more general approach to define arbitrary rotations on lists subsumes your use case of relocating the first N elements to the end of the list.
Try this
despI([C|B],R):-append(B,[C|[]],R).
desp(A,0,A).
desp([C|B],N,R):-N1 is N - 1, despI([C|B],R1), desp(R1,N1,R),!.
The first predicate moves one element to the end of the list, then the only thing I do is "repeat" that N times.
?-de([1,2,3,4],2,R).
R = [3, 4, 1, 2].
?- de([1,2,3,4,5,6,7],4,R).
R = [5, 6, 7, 1, 2, 3, 4].
We can do this with a predicate that works in two phases:
a collect phase: we collect the first N items of the list; and
an emit phase: we construct a list where we add these elements at the tail.
Let is construct the two phases with separate predicate. For the collect phase, we could use the following predicate:
% splitAt(L,N,L1,L2).
splitAt(L,0,[],L).
splitAt([H|T],N,[H|T1],L2) :-
N > 0,
N1 is N-1,
splitAt(T,N1,T1,L2).
Now for the emit phase, we could use append/3. So then the full predicate is:
rotate(L,N,R) :-
splitAt(L,N,L1,L2),
append(L2,L1,R).
This gives:
?- rotate([1,2,3,4],0,R).
R = [1, 2, 3, 4] .
?- rotate([1,2,3,4],1,R).
R = [2, 3, 4, 1] .
?- rotate([1,2,3,4],2,R).
R = [3, 4, 1, 2] .
?- rotate([1,2,3,4],3,R).
R = [4, 1, 2, 3] .
?- rotate([1,2,3,4],4,R).
R = [1, 2, 3, 4].
The algorithm works in O(n).

Prolog Assignment

This is the question for one of my assignments:
Write repCount(L, X, N) which is true when N is the number of occurrences of X in list L.
Here's my code where I try to tackle the problem recursively:
repCount([], X, N) :-
N is 0.
repCount([H|T], X, N) :-
count([H|T], X, N).
count([], X, 0).
count([H|T], X, N) :-
count(T, X, N1),
X =:= H,
N is N1 + 1.
And it works when I supply a list full of identical numbers like this:
?- repCount([2,2,2], 2, N).
N = 3.
But if I supply a list with at least one different value:
?- repCount([2,2,22], 2, N).
false.
It returns false. I cannot figure out why this happens or how to change it to 'skip' the non-matching value, rather than declare the whole thing false. Any input is appreciated.
count([H|T], X, N):- count(T, X, N1), X=:=H, N is N1 + 1.
here you declare that N should be N1+1 if X is H; however you do not define what should happen if X is not H (basically missing an else clause)
this should work:
count([H|T], X, N):-
count(T, X, N1),
(X=:=H->
N is N1 + 1
; N is N1).
another way would be:
count([H|T], X, N):- count(T, X, N1), X=:=H, N is N1 + 1.
count([H|T], X, N):- X=\=H, count(T, X, N1), N is N1.
but this is inefficient since count(T,X,N1) will be called twice if X is not H. we can fix this by doing the check in the head of the clause:
count([H|T], H, N):- count(T, X, N1), N is N1 + 1.
count([H|T], X, N):- count(T, X, N1), N is N1.
or simply:
count([H|T], H, N):- count(T, X, N1), N is N1 + 1.
count([H|T], X, N1):- X=\=H, count(T, X, N1).
One maybe interesting addition to what #magus wrote: If you only care about the number of elements instead of the elements themselves, you can use findall/3 like this:
list_elem_num(Ls, E, N) :-
findall(., member(E, Ls), Ds),
length(Ds, N).
Preserve logical-purity—with a little help from
meta-predicate tcount/3 and (=)/3!
The goal tcount(=(X),Es,N) reads "there are N items in list Es that are equal to X".
Sample query:
?- tcount(=(X), [a,b,c,a,b,c,a,b,a], N).
( N = 4, X=a
; N = 3, X=b
; N = 2, X=c
; N = 0, dif(X,a), dif(X,b), dif(X,c)
). % terminates universally
But assuming you aren't allowed to 'cheat', if you want to use recursion, you don't need to do the '==' comparison.. you can use Prolog's variable unification to reach the same end:
% Job done all instances
repCount2([], _, 0).
% Head unifies with X/2nd parameter - ie X found
repCount2([H|T], H, N) :-
repCount2(T, H, NewN),
N is NewN + 1.
% We got here, so X not found, recurse around
repCount2([_|T], X, N) :-
repCount2(T, X, N).
In the second predicate, H is mentioned twice, meaning that if the Head of the list is the same as X, then recurse down, then add 1 to the result of the rest of the recursion (which ends in adding 0 - the base case, which is how the accumulator is built).
Almost there...you need to use an accumulator, thus:
repCount(Xs,Y,N) :-
count(Xs,Y,0,N) % the 3rd argument is the accumulator for the count, which we seed as 0
.
count([],_,N,N). % if the list is empty, unify the accumulator with the result
count([X|Xs],Y,T,N) :- % if the list is non-empty,
X == Y , % and the head of the list (X) is the the desired value (Y),
T1 is T+1 , % then increment the count, and
count(Xs,Y,T1,N) % recurse down, passing the incremented accumulator
. %
count([X|Xs],Y,T,N) :- % if the list is non-empty,
X \== Y , % and the head of the list(X) is not the desired value (Y),
count(Xs,Y,T,N) % simply recurse down
. %
The original question didn't say whether there were constraints on which predicates you could use.
If you are allowed to 'cheat' ie. use higher order predicates like 'findall' that recurse for you Vs you doing the recursion yourself, this can be done in a single predicate:
repCount(L, X, N) :-
findall(X, member(X, L), ListOfX),
length(ListOfX, N).